|
|
Created:
4 years, 2 months ago by Lasse Reichstein Nielsen Modified:
4 years ago CC:
reviews_dartlang.org Target Ref:
refs/heads/master Visibility:
Public. |
DescriptionChange how the language specification describes control flow.
Changed to compositionally describing how an expression or statement can
complete (normally, throw, return, break, continue), and propagating the
completion to the surrounding statements handling those behaviors.
This should not change the current behavior except in a few cases where
the existing specification was vague, misleading or just wrong.
Actual changes:
- The super call in an initializer list is now always called at the end,
even if it is allowed to be written earlier. This matches existing
VM behavior.
Initialization of initializer expressions are specified
as part of constructor execution, not something happening
at the `new` operator.
- The cancel call to a stream subscription when exiting an async for-in
loop is now made explicit, and its returned future is explicitly
awaited for.
Previously it was unclear what happened with that future.
- Pausing a surrounding async-for loop has been added everywhere
the body of the loop can suspend, just before the suspension.
The loop subscription is not resumed until reaching the end of the body,
which is equivalent to resuming it after each suspend
and then pausing it again when the synchronous execution reaches
the next suspend.
So, easier and doesn't change the behavior of the loop itself,
but it's a visible change if you check the onPause/onResume
of the loop stream.
Spec now recognizes that the pause call may throw on an invalid
implementation of StreamSubscription.
Addresses issues #25859, #25856, #25850, #25848, #25847, #25749, #25634, #25539, #25421, #25412, #25381, #25234, #25005, #24859, #24748, #23779, #23700, #23628, #22908, #21858 (and likely more).
BUG= http://dartbug.com/25859 http://dartbug.com/25856 http://dartbug.com/25850 http://dartbug.com/25848 http://dartbug.com/25847 http://dartbug.com/25749 http://dartbug.com/25634 http://dartbug.com/25539 http://dartbug.com/25421 http://dartbug.com/25412 http://dartbug.com/25381 http://dartbug.com/25234 http://dartbug.com/25005 http://dartbug.com/24859 http://dartbug.com/24748 http://dartbug.com/23779 http://dartbug.com/23700 http://dartbug.com/23628 http://dartbug.com/22908 http://dartbug.com/21858
R=eernst@google.com
Committed: https://github.com/dart-lang/sdk/commit/843bb96813f9a171c7257fcd5e282ff1d323c53d
Patch Set 1 #
Total comments: 126
Patch Set 2 : Merge to head, fix typos #Patch Set 3 : Fix description of "stream raising an error". #
Total comments: 107
Patch Set 4 : Address comments from kmillikin. #
Total comments: 82
Patch Set 5 : Merge to head #Patch Set 6 : First round of comment addresses. #Patch Set 7 : Address remaining comments #Patch Set 8 : Merge to head. Fix typos. #Patch Set 9 : Merge to head #Patch Set 10 : LaTeX fixes #
Total comments: 72
Patch Set 11 : Address comments. #Patch Set 12 : Change LMLabel to label for completion and evaluation. #Patch Set 13 : Without the typo #Patch Set 14 : Update version number #Messages
Total messages: 21 (6 generated)
Description was changed from ========== Change how the language specification describes control flow. Changed to compositionally describing how an expression or statement can complete (normally, throw, return, break, continue), and propagating the completion to the surrounding statements handling those behaviors. This should not change the current behavior except in a few cases where the existing specification was vague, misleading or just wrong. Actual changes: - The super call in an initializer list is now always called at the end, even if it is allowed to be written earlier. This matches existing VM behavior. - The cancel call to a stream subscription when exiting an async for-in loop is now made explicit, and its returned future is explicitly awaited for. Previously it was unclear what happened with that future. - Pausing a surrounding async-for loop has been added everywhere the body of the loop can suspend, just before the suspension. The loop subscription is not resumed until reaching the end of the body, which is equivalent to resuming it after each suspend and then pausing it again when the synchronous execution reaches the next suspend. So, easier and doesn't change the behavior of the loop itself, but it's a visible change if you check the onPause/onResume of the loop stream. Spec now recognizes that the pause call may throw on an invalid implementation of StreamSubscription. ========== to ========== Change how the language specification describes control flow. Changed to compositionally describing how an expression or statement can complete (normally, throw, return, break, continue), and propagating the completion to the surrounding statements handling those behaviors. This should not change the current behavior except in a few cases where the existing specification was vague, misleading or just wrong. Actual changes: - The super call in an initializer list is now always called at the end, even if it is allowed to be written earlier. This matches existing VM behavior. Initialization of initializer expressions are specified as part of constructor execution, not something happening at the `new` operator. - The cancel call to a stream subscription when exiting an async for-in loop is now made explicit, and its returned future is explicitly awaited for. Previously it was unclear what happened with that future. - Pausing a surrounding async-for loop has been added everywhere the body of the loop can suspend, just before the suspension. The loop subscription is not resumed until reaching the end of the body, which is equivalent to resuming it after each suspend and then pausing it again when the synchronous execution reaches the next suspend. So, easier and doesn't change the behavior of the loop itself, but it's a visible change if you check the onPause/onResume of the loop stream. Spec now recognizes that the pause call may throw on an invalid implementation of StreamSubscription. ==========
lrn@google.com changed reviewers: + eernst@google.com, floitsch@google.com
WDYT? If reasonable, I'll forward it to implementors too.
Description was changed from ========== Change how the language specification describes control flow. Changed to compositionally describing how an expression or statement can complete (normally, throw, return, break, continue), and propagating the completion to the surrounding statements handling those behaviors. This should not change the current behavior except in a few cases where the existing specification was vague, misleading or just wrong. Actual changes: - The super call in an initializer list is now always called at the end, even if it is allowed to be written earlier. This matches existing VM behavior. Initialization of initializer expressions are specified as part of constructor execution, not something happening at the `new` operator. - The cancel call to a stream subscription when exiting an async for-in loop is now made explicit, and its returned future is explicitly awaited for. Previously it was unclear what happened with that future. - Pausing a surrounding async-for loop has been added everywhere the body of the loop can suspend, just before the suspension. The loop subscription is not resumed until reaching the end of the body, which is equivalent to resuming it after each suspend and then pausing it again when the synchronous execution reaches the next suspend. So, easier and doesn't change the behavior of the loop itself, but it's a visible change if you check the onPause/onResume of the loop stream. Spec now recognizes that the pause call may throw on an invalid implementation of StreamSubscription. ========== to ========== Change how the language specification describes control flow. Changed to compositionally describing how an expression or statement can complete (normally, throw, return, break, continue), and propagating the completion to the surrounding statements handling those behaviors. This should not change the current behavior except in a few cases where the existing specification was vague, misleading or just wrong. Actual changes: - The super call in an initializer list is now always called at the end, even if it is allowed to be written earlier. This matches existing VM behavior. Initialization of initializer expressions are specified as part of constructor execution, not something happening at the `new` operator. - The cancel call to a stream subscription when exiting an async for-in loop is now made explicit, and its returned future is explicitly awaited for. Previously it was unclear what happened with that future. - Pausing a surrounding async-for loop has been added everywhere the body of the loop can suspend, just before the suspension. The loop subscription is not resumed until reaching the end of the body, which is equivalent to resuming it after each suspend and then pausing it again when the synchronous execution reaches the next suspend. So, easier and doesn't change the behavior of the loop itself, but it's a visible change if you check the onPause/onResume of the loop stream. Spec now recognizes that the pause call may throw on an invalid implementation of StreamSubscription. Addresses issues #25859, #25856, #25850, #25848, #25847, #25749, #25634, #25539, #25421, #25412, #25381, #25234, #25005, #24859, #24748, #23779, #23700, #23628, #22908, #21858 (and likely more). BUG=http://dartbug.com/25859 http://dartbug.com/25856 http://dartbug.com/25850 http://dartbug.com/25848 http://dartbug.com/25847 http://dartbug.com/25749 http://dartbug.com/25634 http://dartbug.com/25539 http://dartbug.com/25421 http://dartbug.com/25412 http://dartbug.com/25381 http://dartbug.com/25234 http://dartbug.com/25005 http://dartbug.com/24859 http://dartbug.com/24748 http://dartbug.com/23779 http://dartbug.com/23700 http://dartbug.com/23628 http://dartbug.com/22908 http://dartbug.com/21858 ==========
Description was changed from ========== Change how the language specification describes control flow. Changed to compositionally describing how an expression or statement can complete (normally, throw, return, break, continue), and propagating the completion to the surrounding statements handling those behaviors. This should not change the current behavior except in a few cases where the existing specification was vague, misleading or just wrong. Actual changes: - The super call in an initializer list is now always called at the end, even if it is allowed to be written earlier. This matches existing VM behavior. Initialization of initializer expressions are specified as part of constructor execution, not something happening at the `new` operator. - The cancel call to a stream subscription when exiting an async for-in loop is now made explicit, and its returned future is explicitly awaited for. Previously it was unclear what happened with that future. - Pausing a surrounding async-for loop has been added everywhere the body of the loop can suspend, just before the suspension. The loop subscription is not resumed until reaching the end of the body, which is equivalent to resuming it after each suspend and then pausing it again when the synchronous execution reaches the next suspend. So, easier and doesn't change the behavior of the loop itself, but it's a visible change if you check the onPause/onResume of the loop stream. Spec now recognizes that the pause call may throw on an invalid implementation of StreamSubscription. Addresses issues #25859, #25856, #25850, #25848, #25847, #25749, #25634, #25539, #25421, #25412, #25381, #25234, #25005, #24859, #24748, #23779, #23700, #23628, #22908, #21858 (and likely more). BUG=http://dartbug.com/25859 http://dartbug.com/25856 http://dartbug.com/25850 http://dartbug.com/25848 http://dartbug.com/25847 http://dartbug.com/25749 http://dartbug.com/25634 http://dartbug.com/25539 http://dartbug.com/25421 http://dartbug.com/25412 http://dartbug.com/25381 http://dartbug.com/25234 http://dartbug.com/25005 http://dartbug.com/24859 http://dartbug.com/24748 http://dartbug.com/23779 http://dartbug.com/23700 http://dartbug.com/23628 http://dartbug.com/22908 http://dartbug.com/21858 ========== to ========== Change how the language specification describes control flow. Changed to compositionally describing how an expression or statement can complete (normally, throw, return, break, continue), and propagating the completion to the surrounding statements handling those behaviors. This should not change the current behavior except in a few cases where the existing specification was vague, misleading or just wrong. Actual changes: - The super call in an initializer list is now always called at the end, even if it is allowed to be written earlier. This matches existing VM behavior. Initialization of initializer expressions are specified as part of constructor execution, not something happening at the `new` operator. - The cancel call to a stream subscription when exiting an async for-in loop is now made explicit, and its returned future is explicitly awaited for. Previously it was unclear what happened with that future. - Pausing a surrounding async-for loop has been added everywhere the body of the loop can suspend, just before the suspension. The loop subscription is not resumed until reaching the end of the body, which is equivalent to resuming it after each suspend and then pausing it again when the synchronous execution reaches the next suspend. So, easier and doesn't change the behavior of the loop itself, but it's a visible change if you check the onPause/onResume of the loop stream. Spec now recognizes that the pause call may throw on an invalid implementation of StreamSubscription. Addresses issues #25859, #25856, #25850, #25848, #25847, #25749, #25634, #25539, #25421, #25412, #25381, #25234, #25005, #24859, #24748, #23779, #23700, #23628, #22908, #21858 (and likely more). BUG= http://dartbug.com/25859 http://dartbug.com/25856 http://dartbug.com/25850 http://dartbug.com/25848 http://dartbug.com/25847 http://dartbug.com/25749 http://dartbug.com/25634 http://dartbug.com/25539 http://dartbug.com/25421 http://dartbug.com/25412 http://dartbug.com/25381 http://dartbug.com/25234 http://dartbug.com/25005 http://dartbug.com/24859 http://dartbug.com/24748 http://dartbug.com/23779 http://dartbug.com/23700 http://dartbug.com/23628 http://dartbug.com/22908 http://dartbug.com/21858 ==========
DBC. Haven't yet finished the review... https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.tex File docs/language/dartLangSpec.tex (right): https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1: 4\documentclass{article} typo? https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1397: which must happen in the order the expressions occour in the program text. occur
https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.tex File docs/language/dartLangSpec.tex (right): https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1: 4\documentclass{article} That, or advanced LaTeX magic - who knows? (LaTeX knows, fixed). https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:6159: The \RETHROW{} statement aborts by {\em throwing} with $p_1$ as the exception object and $p_2$ as the stack trace. Another option, and probably more consistent, is to introduce "rethrows" as a way for statements to complete, and then in the catch body evaluation, if it completes by rethrowing, throw with the exception and stack that was used to enter the catch body. Those values will still be logically in scope at that point. WDYT?
kmillikin@google.com changed reviewers: + kmillikin@google.com
https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.tex File docs/language/dartLangSpec.tex (right): https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:2376: Expressions can also {\em throw} an exception object and an associated stack trace. I suggest a more radical rewrite of this section. It should say up front that there are two possibilities, and then provide specific details of the two. It should be clear that the two possibilities are mutually exclusive (say "or else" instead of "or"). The two possibilities should use parallel language wherever possible. As it is, the detail "Every expression has an associated static type" is lumped in with yielding a value, but that detail is true of expressions that throw exceptions as well so it should appear where both outcomes are discussed. The terminology "yield a value" is unfortunate. I think we need to go with something more like "produce a value". Though note that elsewhere we simply use "evaluates to" so we could simply have that expressions evaluate to a value or else throw an exception. The emphasis is inconsistent --- why emphasize 'value' but not 'exception'? Why emphasize 'throw' but not 'yield'? https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:2429: The predefined Dart function \cd{identical()} is defined such that \code{identical($c_1$, $c_2$)} iff: Consider this outside the scope of this change, but this section should be cleaned up. "... is defined such that the expression identical(c_1, c_2) evaluates to the boolean object true iff: ... otherwise identical(c_1, c_2) evaluates to the boolean object false. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:2431: \item $c_1$ evaluates to either \NULL{} or an instance of \code{bool} and \code{$c_1$ == $c_2$}, OR c_1 can't actually evaluate to null, null is a reserved word that denotes (evaluates to?) the null object. Write: "c_1 evaluates to either the null object..." (Though we repeatedly use the reserved word null to mean the null object, and the same with the reserved words true and false. Maybe what is actually meant by "...null denotes the null object..." is "the expression null evaluates to the null object and we will use the reserved word null to mean the null object". I still think we could spell it out.) Also we can spell out what 'c_1 == c_2' means (it is ambiguous to treat it like a predicate that the spec can use here. All it is is an expression that possibly evaluates to a value. Perhaps it just means that that expression terminates? Or produces a value and doesn't throw?). Write: 'c1 == c2 evaluates to the boolean value true'. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:2432: \item $c_1$ and $c_2$ are instances of \code{int} and \code{$c_1$ == $c_2$}, OR c_1 and c_2 are expressions, so they are not instances of anything. Write c_1 and c_2 evaluate to instances.... https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:2433: \item $c_1$ and $c_2$ are constant strings and \code{$c_1$ == $c_2$}, OR The spec defines constant expressions, not constant values. This clause seems to make identical not really a Dart function (at least, it's a function that gets to know the syntactic form of its arguments). I've never been able to figure out if the intent is to require: var x = "Hello, world!"; ... identical(x, "Hello, world!") ... to be true or not. I think it doesn't require that: the literal string is a constant, but the identifier expression does not denote a constant variable.
This approach is definitely simpler. I still haven't read it all closely. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... File docs/language/dartLangSpec.tex (right): https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:327: {\em Run-time errors} are exceptions raised during execution. Whenever we say that an exception $ex$ is {\em raised} or {\em thrown}, we mean that a throw expression (\ref{throw}) of the form: \code{\THROW{} $ex$;} was implicitly evaluated or that a rethrow statement (\ref{rethrow}) of the form \code{\RETHROW} was executed. When we say that {\em a} $C$ {\em is thrown}, where $C$ is a class, we mean that an instance of class $C$ is thrown. When we say that a stream raises an exception, we mean that the stream emits the exception and its associated stack trace as an error event. I'd be quite happy if we only every said "raised" or else "thrown" and never mixed the two. It's a bit circular to use "an exception was thrown" here and "throw an exception" as a possible outcome of expression evaluation. I don't know in what context "an exception $ex$ is raised" can mean that a rethrow statement was executed, so this at least needs to be more specific. I prefer to just say directly here what happens when an exception is raised and then just say that 'throw' does that thing, rather than saying here that raising an exception is implicitly evaluating an expression and putting the details in the evaluation of throw. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:2588: The reserved word \NULL{} denotes the {\em null object}. "denotes" ==> "evaluates to" https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:2638: If a numeric literal begins with the prefix `0x' or `0X', it denotes the hexadecimal integer represented by the part of the literal following `0x' (respectively `0X'). Otherwise, if the numeric literal contains only decimal digits, it denotes a decimal integer. Otherwise, the numeric literal contains either a decimal point or an exponent part and it denotes a 64 bit double precision floating point number as specified by the IEEE 754 standard. "denotes" => "evaluates to" https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:2651: An {\em integer literal} is either a hexadecimal integer literal or a decimal integer literal. Invoking the getter \code{runtimeType} on an integer literal returns the \code{Type} object that is the value of the expression \code{int}. The static type of an integer literal is \code{int}. Definitely outside the scope of this change: do we intend the part about runtimeType to apply to integer values, or only integer literals? I think values otherwise we end up with some strange cases such as identical(42, true ? 42 : 42) but 42.runtimeType not required to be the same as (true ? 42 : 42).runtimeType. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:2661: The reserved words \TRUE{} and \FALSE{} denote objects that represent the boolean values true and false respectively. They are the {\em boolean literals}. "denote" => "evaluate to" https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:2670: Both \TRUE{} and \FALSE{} implement the built-in class \code{bool}. It is a compile-time error for a class to attempt to extend, mix in or implement\code{ bool}. A class can implement an interface and we sometimes say a type can implement an interface, but a value cannot implement an interface (nor can a reserved word). I think this has to be that the run-time types of the true and false values implement the built-in class bool (the static type is of course, bool). https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:2677: Invoking the getter \code{runtimeType} on a boolean literal returns the \code{Type} object that is the value of the expression \code{bool}. The static type of a boolean literal is \code{bool}. "literal" ==> "value" or "object"? https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:2878: All string literals implement the built-in class \code{String}. It is a compile-time error for a class to attempt to extend, mix in or implement \code{String}. Invoking the getter \code{runtimeType} on a string literal returns the \code{Type} object that is the value of the expression \code{String}. The static type of a string literal is \code{String}. A literal can't implement an interface. A literal is syntax and I think these requirement applies to string values. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:2903: The form \code{\$id} is equivalent to the form \code{\$\{id\}}. An interpolated string \code{`$s_1$\$\{$e$\}$s_2$'} is equivalent to the concatenation of the strings \code{`$s_1$'}, \code{$e$.toString()} and \code{$`s_2$'}. Likewise an interpolated string \code{``$s_1$\$\{e\}$s_2$''} is equivalent to the concatenation of the strings \code{``$s_1$''}, \code{$e$.toString()} and \code{``$s_2$''}. Note that this doesn't explicitly impose a left-to-right evaluation order, which makes a difference if an expression throws. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3102: If $e$ evaluates to \NULL{} (\ref{null}), then a \code{NullThrownError} is thrown. Otherwise let $t$ be a stack trace corresponding to the current execution state, and the \THROW{} statement aborts by {\em throwing} with $e$ as exception object and $t$ as stack trace. $e$ evaluates to ==> $v$ is Throw is an expression so this has to be: Otherwise let $t$ be a stack trace corresponding to the current execution state. The \THROW{} expression {\em throws} the value $v$ as exception and $t$ as stack trace. (Note that we probably want "throws the value v" because "throws v" will look weird when they are both italicized.) https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3105: If $e$ is an instance of class \code{Error} or a subclass thereof, its \code{stackTrace} getter will return the stack trace captured at the point where the object was first thrown. $e$ ==> $v$ Maybe captured isn't quite right, we don't speak of stack traces as being captured. Above they correspond to execution state so the language here should parallel: "...return the stack trace corresponding to the execution state at the point...". https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3108: If the same \code{Error} object is thrown more than once, its \code{stackTrace} getter will return the stack trace captured the {\em first} time it was thrown. Same comment about captured. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3373: Otherwise, if $q$ is not defined or not accessible, a \code{NoSuchMethodError} is thrown. If $q$ has less than $n$ positional parameters or more than $n$ required parameters, or if $q$ lacks any of the keyword parameters $\{ x_{n+1}, \ldots, x_{n+k}\}$ a \code{NoSuchMethodError} is thrown. less ==> fewer https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3564: If $f$ is marked \ASYNC{} (\ref{functions}), then a fresh instance (\ref{generativeConstructors}) $o$ implementing the built-in class \code{Future} is associated with the invocation and immediately returned to the caller. The body of $f$ is scheduled for execution at some future time. The future $o$ will complete when execution of $f$ completes (\ref{completion}). If $f$ completes by {\em returning} a value, that value used to complete $o$, if it {\em completes normally} or by {\em returning} with no value, $o$ is completed with \NULL{}, and if it completes by {\em throwing} an exception $e$ and stack trace $t$, $o$ is completed with $e$ and stack trace $t$ as an error. I think this has to be "when execution of the body of $f completes" because it is the body that is scheduled for execution at some future time and the execution of $f$ seems to complete immediately (synchronously). Note that we still have in Section 9 that function bodies have return appended to them, so I think it is impossible for the body of f to complete normally. However, I would be quite happy if we got rid of the part about appending return in Section 9. Have you considered what the possibility of "returning no value" might do to the type system? Do we just not care about checked mode any more? We need to avoid splitting 'o is completed ... as an error' up because it reads like the future is completing with a stack trace. The API docs are nice in this regard, they use "complete with a value" and "complete with an error". It's a bigger change, but it seems nicer to start with the synchronous case in this section rather than async. I suggest mentioning that the possibilities break and continue are impossible because it is a compile time error for a function to contain them wherever they would complete the function body. It is very unfortunate that this is written in terms of "(the function) f" completing. That might lead to a reading where if the body of the function f completes, than all futures associated with any invocation of f are completed. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3567: If $f$ is marked \ASYNC* (\ref{functions}), then a fresh instance $s$ implementing the built-in class \code{Stream} is associated with the invocation and immediately returned. When $s$ is listened to, execution of the body of $f$ will begin. When $f$ completes: When the body of f completes. We also should find language making it clear that it is the execution of the body of f associated with s that we care about, not when the function f generally completes. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3569: \item If $f$ {\em completes normally}, then if $s$ has been canceled then its cancellation future is completed with \NULL{} (\ref{null}). the body of f https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3570: \item If $f$ {\em throws} exception $e$ and stack trace $t$: the body of f https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3576: \end{itemize} Perhaps here mention that the possibilities break, continue, and returning a value are impossible. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3601: When iteration over the iterable is started, by getting an iterator $j$ from the iterable and calling \code{moveNext()}, execution of the body of $f$ will begin. When $f$ completes (\ref{completion}, the body of f https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3603: \item If $f$ {\em completes normally}, $j$ is positioned after its last element, so that its current value is \NULL{} and the current call to \code{moveNext()} on $j$ returns false, as will all further calls. the body of f https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3604: \item If $f$ {\em throws} exception $e$ and stack trace $t$ then the current value is \NULL{} and the current call to \code{moveNext()} throws $e$ and $t$ as well. Further calls must return false. the body of f https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3627: When $f$ completes (\ref{completion}) by returning a value, that value is returned to the caller. When ==> If that value is returned to the caller ==> the value of the function invocation is that value Perhaps name the value v so you can mention it less awkwardly. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3628: If $f$ completes by returning without a value or by completing normally, \NULL{} is returned to the callee. Definitely not callee :) null is returned ==> the value of the function invocation (alternately: invocation of f) is null. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3632: A function body can never {\em abort} by {\em breaking} or {\em continuing} abort ==> complete https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3637: This means that a function body can only abort by {\em throwing} or by {\em returning} a value, so a function call expression can always propagate the behavior of the called function's body. abort ==> complete https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5038: % NOTICE: Removed the requirement that an error thrown by $e$ is caught in a Thank you! https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5041: If $e$ evaluates to an object $o$ that is not an instance of \code{Future}, then let $f$ be the result of creating a new object using the constructor \code{Future.value()} with $o$ as its argument; otherwise let $f$ be the result of evaluating $e$. The result of evaluating e is o (or maybe an exception, but you can't let f be the result of that because it's a pair). I think we want: If $e$ evaluates to an object $o$, and if $o$ is not an instance of \code{Future}, then let $f$ be the result of creating a new object using the constructor \code{Future.value()} with $o$ as its argument; otherwise let $f$ be $o$. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5044: Next, the stream associated with the innermost enclosing asynchronous for loop (\ref{asynchronousFor-in}), if any, is paused. Execution of the function $m$ immediately enclosing $a$ is suspended until after $f$ completes. At some time after $f$ is completed, control returns to the current invocation. If $f$ has completed with an exception $x$ and stack trace $t$, $a$ {\em throws} $x$ and $t$. If $f$ completes with a value $v$, $a$ evaluates to $v$. I would say that we're not really executing the function $m$, we are executing its body. The actual function $m$ has already returned. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5458: Some statements can affect control flow, in particular \BREAK{}, \CONTINUE{}, \RETURN{} and \THROW{} statements. Throw is not a statement, but rethrow is. If you want to mention throw, you will need something like 'statements containing throw expressions'. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5461: Execution of a statement can {\em complete} in two ways: either it {\em completes normally} or it {\em aborts}. It can {\em abort} in one of four ways: Either it {\em breaks} or it {\em continues} (either to a label or without a label), it {\em returns}, either with a value or without one, or it {\em throws} an exception object and an associated stack trace. Instead of two possibilities, one of which is four possibilities, how about just five possibilities? https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5743: The expression $[v^\prime/v]c$ is evaluated and subjected to boolean conversion (\ref{booleans}). If the result is \FALSE{}, the for loop completes. Otherwise, execution continues at step completes ==> completes normally https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5888: If that execution completes normally or it {\em continues} with no label or with a label that prefixes the \WHILE{} statement (\ref{labels}), then the while statement is re-executed. For 'for' we have the language "a label that this \FOR{} statement is labeled with". Here is is prefixed. It should be exactly parallel whatever we settle on. Also, for 'for' we mention explicitly the other possibilities, here we rely on the convention that they aren't mentioned so the while statement does the same thing. We should be consistent one way or the other (it's fine to not mention them). \ref{labels} should be on "a label" or "no label", it looks weird on "while statement". https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6013: The statement \code{\VAR{} id = $e$;} is evaluated, where \code{id} is a variable whose name is distinct from any other variable in the program. In checked mode, it is a run time error if the value of $e$ is not an instance of the same class as the constants $e_1 \ldots e_n$. Since you've explicitly defined matching against a value (parameterized over the value, instead of explicitly against id) we do not need to introduce this fresh variable id any more. Just say e is evaluated to v. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6018: Next, the case clause \CASE{} $e_{1}: s_{1}$ is matched against {\code id} if it exists. If \CASE{} $e_{1}: s_{1}$ does not exist, then if there is a \DEFAULT{} clause, its statements, if any, are executed (\ref{case-execute}). It sounds like id might not exist. I would say something like: if the case clause ... exists it is matched against v. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6039: If $v$ is not \TRUE{} the following case, \CASE{} $e_{k+1}: s_{k+1}$ is matched against {\code id} if it exists. If \CASE{} $e_{k+1}: s_{k+1}$ does not exist, then the \DEFAULT{} clause's statements are executed (\ref{case-execute}). Again, it sounds like id might not exist. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6056: The expression \code{$e_k$ == id} is evaluated to an object $o$ which is then subjected to boolean conversion yielding a value $v$. Note that there may be zero cases, so you need the "if it exists" langauge here too. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6061: \subsection{ Executing the statements of a switch case} Should be a subsubsection of switch I think. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6087: Execute $\{s_h\}$. Note that the language about how a case clause introduce a new scope, and where that scope ends, is actually now unnecessary. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6088: If this execution completes normally, and if $s_h$ is not the statements of the last case of the switch ($h = n$ if there is no \DEFAULT{} clause, $h = n+1$ if there is a \DEFAULT{} clause), then the execution of the switch case aborts by throwing a runtime error. Otherwise $s_h$ are the last statements of the switch case, and execution of the switch case completes normally. aborts ==> completex https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6104: It is a static warning if the type of $e$ may not be assigned to the type of $e_k$. It is a static warning if the last statement of the statement sequence $s_k$ is not a \BREAK{}, \CONTINUE{}, \RETURN{} or \THROW{} statement. This paragraph and the rest of this section is out of place in the subsection about executing statements. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6495: \item The getter \cd{current} is invoked on $i$. If the invocation {\em throws} an exception $ex$, execution of $s$ aborts in the same way. Otherwise, the result $x$ of the getter invocation is added to the iterable associated with $m$. I've always thought that calling current here is weird, because nobody has yet called current on the outer iterator. This has the consequence that if we have yield* e, and calling current throws for some reason, we can never get the rest of the stuff from e because the yield* has completed.
https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.tex File docs/language/dartLangSpec.tex (right): https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:2376: Expressions can also {\em throw} an exception object and an associated stack trace. Rewritten completely. Changed "yield" to "produce" everywhere(?) it refers to evaluation of an expression. The emphasis is inconsistent. I don't want to emphasize a long sentence part like "throws an exeception object and an associated stack trace", so I now just emphasize "throws". On the other hand, just emphasizing "produces" seems weird without "a value". Maybe it's just because I'm used to using "throws" intransitively, but not "produces". Better ideas appreciated. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:2429: The predefined Dart function \cd{identical()} is defined such that \code{identical($c_1$, $c_2$)} iff: ACK. Definitely out of scope for this CL. Definitely could use an update. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... File docs/language/dartLangSpec.tex (right): https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:327: {\em Run-time errors} are exceptions raised during execution. Whenever we say that an exception $ex$ is {\em raised} or {\em thrown}, we mean that a throw expression (\ref{throw}) of the form: \code{\THROW{} $ex$;} was implicitly evaluated or that a rethrow statement (\ref{rethrow}) of the form \code{\RETHROW} was executed. When we say that {\em a} $C$ {\em is thrown}, where $C$ is a class, we mean that an instance of class $C$ is thrown. When we say that a stream raises an exception, we mean that the stream emits the exception and its associated stack trace as an error event. I thought about removing the `rethrow` part, but apparently forgot. The only reason I didn't rewrite this to directly say that it "throws expression and stack trace as if an expression has thrown" was that I then also needed to duplicate the part about creating a stack trace corresponding to the current state.. (This comment is probably already about as long as that, so that one saving didn't pay for itself). I'll remove "raise" and just use "throw", and rewrite this section. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:2588: The reserved word \NULL{} denotes the {\em null object}. On 2016/10/13 12:18:37, Kevin Millikin (Google) wrote: > "denotes" ==> "evaluates to" Done. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:2638: If a numeric literal begins with the prefix `0x' or `0X', it denotes the hexadecimal integer represented by the part of the literal following `0x' (respectively `0X'). Otherwise, if the numeric literal contains only decimal digits, it denotes a decimal integer. Otherwise, the numeric literal contains either a decimal point or an exponent part and it denotes a 64 bit double precision floating point number as specified by the IEEE 754 standard. Rewritten entire section. Not sure it makes complete sense yet - it's hard to distinguish concrete syntax (sequence of characters), abstract numerals (sequence of digits), integers (Z) and `int` instances (objects) without being confusing. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:2651: An {\em integer literal} is either a hexadecimal integer literal or a decimal integer literal. Invoking the getter \code{runtimeType} on an integer literal returns the \code{Type} object that is the value of the expression \code{int}. The static type of an integer literal is \code{int}. It should apply to all integers, and the spec is imposing itself on the libraries unnecessarily here. An *integer value* (or object) is an instance of the class `int`, and unsurprisingly, its runtimeType returns the Type object corresponding to the `int` class. There is no reason to say that. So I removed them all. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:2661: The reserved words \TRUE{} and \FALSE{} denote objects that represent the boolean values true and false respectively. They are the {\em boolean literals}. Rewritten to distinguish syntax from `bool` instances and abstract logical values. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:2670: Both \TRUE{} and \FALSE{} implement the built-in class \code{bool}. It is a compile-time error for a class to attempt to extend, mix in or implement\code{ bool}. Changed to "are instances of". The spec is a little inconsistent about that phrase. Sometimes it means "somthing that would satisfy an `is` check" (aka, subtype of) but I also *think* that in a few cases it means "instance of that exact class, not a subclass". https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:2677: Invoking the getter \code{runtimeType} on a boolean literal returns the \code{Type} object that is the value of the expression \code{bool}. The static type of a boolean literal is \code{bool}. Removed. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:2878: All string literals implement the built-in class \code{String}. It is a compile-time error for a class to attempt to extend, mix in or implement \code{String}. Invoking the getter \code{runtimeType} on a string literal returns the \code{Type} object that is the value of the expression \code{String}. The static type of a string literal is \code{String}. On 2016/10/13 12:18:36, Kevin Millikin (Google) wrote: > A literal can't implement an interface. A literal is syntax and I think these > requirement applies to string values. Done. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:2903: The form \code{\$id} is equivalent to the form \code{\$\{id\}}. An interpolated string \code{`$s_1$\$\{$e$\}$s_2$'} is equivalent to the concatenation of the strings \code{`$s_1$'}, \code{$e$.toString()} and \code{$`s_2$'}. Likewise an interpolated string \code{``$s_1$\$\{e\}$s_2$''} is equivalent to the concatenation of the strings \code{``$s_1$''}, \code{$e$.toString()} and \code{``$s_2$''}. And it doesn't cover the case where e.toString doesn't return a string. Rewritten completely, PTAL. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3102: If $e$ evaluates to \NULL{} (\ref{null}), then a \code{NullThrownError} is thrown. Otherwise let $t$ be a stack trace corresponding to the current execution state, and the \THROW{} statement aborts by {\em throwing} with $e$ as exception object and $t$ as stack trace. -> If $v$ is the null value (as you correctly point out elsewhere \NULL is syntax, not value). -> throws (\ref{completion}) with $v$ as exception and $t$ as stack trace. That's the pattern I'm generally using for throwing. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3105: If $e$ is an instance of class \code{Error} or a subclass thereof, its \code{stackTrace} getter will return the stack trace captured at the point where the object was first thrown. Rewritten. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3108: If the same \code{Error} object is thrown more than once, its \code{stackTrace} getter will return the stack trace captured the {\em first} time it was thrown. captured->from https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3373: Otherwise, if $q$ is not defined or not accessible, a \code{NoSuchMethodError} is thrown. If $q$ has less than $n$ positional parameters or more than $n$ required parameters, or if $q$ lacks any of the keyword parameters $\{ x_{n+1}, \ldots, x_{n+k}\}$ a \code{NoSuchMethodError} is thrown. On 2016/10/13 12:18:37, Kevin Millikin (Google) wrote: > less ==> fewer Done. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3564: If $f$ is marked \ASYNC{} (\ref{functions}), then a fresh instance (\ref{generativeConstructors}) $o$ implementing the built-in class \code{Future} is associated with the invocation and immediately returned to the caller. The body of $f$ is scheduled for execution at some future time. The future $o$ will complete when execution of $f$ completes (\ref{completion}). If $f$ completes by {\em returning} a value, that value used to complete $o$, if it {\em completes normally} or by {\em returning} with no value, $o$ is completed with \NULL{}, and if it completes by {\em throwing} an exception $e$ and stack trace $t$, $o$ is completed with $e$ and stack trace $t$ as an error. I ignored the added return of section 9 because I consider removing it. This is "defensive specification", handling even cases that can't happen (which is a bad idea in general, but I hadn't decided on removing the extra return). Keeping it does mean that I can avoid handling the "completes normally" case for function invocations, and there is some consistency to not being able to "fall through" the bottom of a function body - all jumps between functions are explicit. Still not decided. I'll remove either one before committing, if I can decide on which. Good point about distinguishing invocation of function from execution of body (and there really is no "execution of function"). "Returning no value" cannot leak a function invocation - it is converted into a `null` value at the point where the "return with no value" reaches the end of the function body and becomes the value of an invocation. Still, I don't think the distinction between returning null and returning with no value is needed, so I'll just remove the "returning with no value" option and just "return null" instead. I initially thought I needed the distinction for generative constructors, but they're syntactically constrained from containing `return e;` so I don't have to care. Changed order to sync, sync*, async, async*. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3567: If $f$ is marked \ASYNC* (\ref{functions}), then a fresh instance $s$ implementing the built-in class \code{Stream} is associated with the invocation and immediately returned. When $s$ is listened to, execution of the body of $f$ will begin. When $f$ completes: On 2016/10/13 12:18:38, Kevin Millikin (Google) wrote: > When the body of f completes. We also should find language making it clear that > it is the execution of the body of f associated with s that we care about, not > when the function f generally completes. Done. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3569: \item If $f$ {\em completes normally}, then if $s$ has been canceled then its cancellation future is completed with \NULL{} (\ref{null}). On 2016/10/13 12:18:36, Kevin Millikin (Google) wrote: > the body of f Done. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3570: \item If $f$ {\em throws} exception $e$ and stack trace $t$: On 2016/10/13 12:18:37, Kevin Millikin (Google) wrote: > the body of f Done. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3576: \end{itemize} On 2016/10/13 12:18:37, Kevin Millikin (Google) wrote: > Perhaps here mention that the possibilities break, continue, and returning a > value are impossible. Done. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3601: When iteration over the iterable is started, by getting an iterator $j$ from the iterable and calling \code{moveNext()}, execution of the body of $f$ will begin. When $f$ completes (\ref{completion}, On 2016/10/13 12:18:38, Kevin Millikin (Google) wrote: > the body of f Done. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3603: \item If $f$ {\em completes normally}, $j$ is positioned after its last element, so that its current value is \NULL{} and the current call to \code{moveNext()} on $j$ returns false, as will all further calls. On 2016/10/13 12:18:37, Kevin Millikin (Google) wrote: > the body of f Done. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3604: \item If $f$ {\em throws} exception $e$ and stack trace $t$ then the current value is \NULL{} and the current call to \code{moveNext()} throws $e$ and $t$ as well. Further calls must return false. On 2016/10/13 12:18:38, Kevin Millikin (Google) wrote: > the body of f Done. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3627: When $f$ completes (\ref{completion}) by returning a value, that value is returned to the caller. On 2016/10/13 12:18:37, Kevin Millikin (Google) wrote: > When ==> If > > that value is returned to the caller ==> the value of the function invocation is > that value > > Perhaps name the value v so you can mention it less awkwardly. Done. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3628: If $f$ completes by returning without a value or by completing normally, \NULL{} is returned to the callee. -> the invocation evaluates to \code{null}. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3632: A function body can never {\em abort} by {\em breaking} or {\em continuing} On 2016/10/13 12:18:36, Kevin Millikin (Google) wrote: > abort ==> complete Done. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:3637: This means that a function body can only abort by {\em throwing} or by {\em returning} a value, so a function call expression can always propagate the behavior of the called function's body. On 2016/10/13 12:18:36, Kevin Millikin (Google) wrote: > abort ==> complete Done. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5038: % NOTICE: Removed the requirement that an error thrown by $e$ is caught in a On 2016/10/13 12:18:36, Kevin Millikin (Google) wrote: > Thank you! Acknowledged. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5041: If $e$ evaluates to an object $o$ that is not an instance of \code{Future}, then let $f$ be the result of creating a new object using the constructor \code{Future.value()} with $o$ as its argument; otherwise let $f$ be the result of evaluating $e$. On 2016/10/13 12:18:36, Kevin Millikin (Google) wrote: > The result of evaluating e is o (or maybe an exception, but you can't let f be > the result of that because it's a pair). I think we want: > > If $e$ evaluates to an object $o$, and if $o$ is not an instance of > \code{Future}, then let $f$ be the result of creating a new object using the > constructor \code{Future.value()} with $o$ as its argument; otherwise let $f$ be > $o$. Done. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5044: Next, the stream associated with the innermost enclosing asynchronous for loop (\ref{asynchronousFor-in}), if any, is paused. Execution of the function $m$ immediately enclosing $a$ is suspended until after $f$ completes. At some time after $f$ is completed, control returns to the current invocation. If $f$ has completed with an exception $x$ and stack trace $t$, $a$ {\em throws} $x$ and $t$. If $f$ completes with a value $v$, $a$ evaluates to $v$. Reworded. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5458: Some statements can affect control flow, in particular \BREAK{}, \CONTINUE{}, \RETURN{} and \THROW{} statements. Reworded. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5461: Execution of a statement can {\em complete} in two ways: either it {\em completes normally} or it {\em aborts}. It can {\em abort} in one of four ways: Either it {\em breaks} or it {\em continues} (either to a label or without a label), it {\em returns}, either with a value or without one, or it {\em throws} an exception object and an associated stack trace. On 2016/10/13 12:18:37, Kevin Millikin (Google) wrote: > Instead of two possibilities, one of which is four possibilities, how about just > five possibilities? Done. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5743: The expression $[v^\prime/v]c$ is evaluated and subjected to boolean conversion (\ref{booleans}). If the result is \FALSE{}, the for loop completes. Otherwise, execution continues at step On 2016/10/13 12:18:38, Kevin Millikin (Google) wrote: > completes ==> completes normally Done. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5888: If that execution completes normally or it {\em continues} with no label or with a label that prefixes the \WHILE{} statement (\ref{labels}), then the while statement is re-executed. It seems "prefixes" is the wording used in most other places, so I'll go for that for now. The label is referring to what it means to prefix a statement, so I think it is located correctly. The a label or no label should refer \ref{completion} because those terms are defined there. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6013: The statement \code{\VAR{} id = $e$;} is evaluated, where \code{id} is a variable whose name is distinct from any other variable in the program. In checked mode, it is a run time error if the value of $e$ is not an instance of the same class as the constants $e_1 \ldots e_n$. We actually do use `id` below in the expression $e_k == id$. This is shorter than having to unfold the definition of `==` operator (which is not just calling the `operator==` method - it also checks both sides for null, and in non-checked mode that can happen). It's definitely not perfect, but I won't try to fix this now. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6021: A case clause introduces a new scope, nested in the lexically surrounding scope. The scope of a case clause ends immediately after the case clause's statement list. Removed https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6039: If $v$ is not \TRUE{} the following case, \CASE{} $e_{k+1}: s_{k+1}$ is matched against {\code id} if it exists. If \CASE{} $e_{k+1}: s_{k+1}$ does not exist, then the \DEFAULT{} clause's statements are executed (\ref{case-execute}). On 2016/10/13 12:18:36, Kevin Millikin (Google) wrote: > Again, it sounds like id might not exist. Done. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6056: The expression \code{$e_k$ == id} is evaluated to an object $o$ which is then subjected to boolean conversion yielding a value $v$. I don't think that is necessary, it's handled at the "call" point for this sub-execution. The "matching a value against an case clause" is only invoked above or below in the case where such a case clause exists (due to the "if such a clause exists" text), so we only get here if there is one. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6061: \subsection{ Executing the statements of a switch case} Absolutely, and should have a more consistent name too. Other section/subsection names are shorter. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6087: Execute $\{s_h\}$. On 2016/10/13 12:18:36, Kevin Millikin (Google) wrote: > Note that the language about how a case clause introduce a new scope, and where > that scope ends, is actually now unnecessary. Done. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6088: If this execution completes normally, and if $s_h$ is not the statements of the last case of the switch ($h = n$ if there is no \DEFAULT{} clause, $h = n+1$ if there is a \DEFAULT{} clause), then the execution of the switch case aborts by throwing a runtime error. Otherwise $s_h$ are the last statements of the switch case, and execution of the switch case completes normally. On 2016/10/13 12:18:38, Kevin Millikin (Google) wrote: > aborts ==> completex Done. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6104: It is a static warning if the type of $e$ may not be assigned to the type of $e_k$. It is a static warning if the last statement of the statement sequence $s_k$ is not a \BREAK{}, \CONTINUE{}, \RETURN{} or \THROW{} statement. Moved it to before the subsection. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6495: \item The getter \cd{current} is invoked on $i$. If the invocation {\em throws} an exception $ex$, execution of $s$ aborts in the same way. Otherwise, the result $x$ of the getter invocation is added to the iterable associated with $m$. This is the *simple* implementation which is basically equivalent to: for (var $ in e) yield $; The behavior you are asking for is more involved. It requires the execution to maintain extra state at all times - the "current yield* iterator". While that is set, the sync* function body is suspended. Any call to "moveNext" must first check if there is a current iterator, and if there is, call its moveNext. Then, if that call returns true, return true, otherwise clear the current yield* iterator and resume the sync* function body (the yield8 either completes normally or throws, depending on what moveNext did). When you call the "current" getter of the sync* iterator, it first checks if there is a current iterator, and if there is, it calls the "current" getter of that iterator instead (and either returns or throws the same way), otherwise it returns the current value last yielded by the sync* funtion body. It's doable, but we need to specify the behavior of the returned Iterator for both "current" and "moveNext", we can't just pretend there is a "current" value that we can assign to. I'm not sure this other behavior is better. It requires on extra field of storage, and one extra check at the beginning of "moveNext" and "current", but that's small potatoes compared to the rest of the sync* machinery, especially the way it's currently implemented. It makes the specification more complicated (but then, I could make it less complicated by saying that "yield* e;" is equivalent to "for (var $ in e) yield $;", which would be completely true for the current specification, and I haven't done that). I'm not sure it'll actually help any user to make the change, but I can be convinced. It's a prettier model that yield* just forwards moveNext and current to the new stream, and it might enable a more efficient implementation strategy (not that I have one in mind).
OK, I reached line 5800 at this point, and it goes on and on. Here are my comments so far, I'll continue tomorrow. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.tex File docs/language/dartLangSpec.tex (right): https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1: 4\documentclass{article} Make it 5. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1215: A {\em generative constructor} is executed to initialize a freshly allocated object. Even though it is tempting to add explanatory text like the above, I think that the intended information is already given at the beginning of `\subsection{Constructors}` ('[constructors are] used .. to produce objects'), so I'd recommend that we avoid adding it here, in normative text, and simply stick to the syntax description, as before. Other mechanisms like instance methods, getters, setters, and functions are also introduced by their syntax, and the semantics is specified in detail (usually by words along the lines of '..the body is executed..') when we get to the point where the necessary preconditions have been established. So, in general, "semantic summaries" like this are used quite rarely in normative text. We could add a bit of semantic summary material to all the constructs involving execution. but that would make the spec longer and more redundant. If we still decide that we want to have these semantic summaries then I think we should make it explicit that the semantics of the generative constructor includes allocation, otherwise the words 'freshly allocated' will raise the question "OK, so how do we allocate it in the first place?". Also, I find the words 'is executed to initialize' too ambiguous, I'd prefer something like 'The effect of executing a {\em generative constructor} is to allocate and initialize a new object', and even then I'd prefer to have the introduction of the syntax at first, such that we have the generative constructor "on the table", and then we can say what it does. PS: Further down the text I can see that the allocation operation has been kept (deliberately?) hidden, so we may need to search for the right place to put it. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1298: % Need to specify exactly how executing a redirecting constructor works I think the new text in lines 1288-1297 is redundant: The semantics of an execution of a redirecting generative constructor is specified later in `\section{Generative Constructors}` (search for 'If $k$ is redirecting..' line 1360), along with text before and after that point specifying elements that are shared among multiple kinds of constructors. We should instead delete the comment in line 1298, which is probably a TODO from before the text around 'If $k$ is redirecting' was written. Alternatively, if we wish to include this kind of semantic summary then we could add a \commentary{} about it. But I think we should be careful about introducing that kind of redundancy, because it incurs the danger of making the spec significantly longer. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1351: Execution of a generative constructor $k$ to initialize a fresh instance $i$ I think we need to preserve the information about the binding of `\THIS{}`. I can see that the phrase 'to initialize a fresh instance $i$' plays a different role here and below: It is a fixed phrase used in connection with the execution of generative constructors. The benefit is that this allows for the description to hold a given constructor and the instance currently-in-construction on the table, such that there can be a location in the spec where the two of them are brought together, and then we can describe the execution of several constructors with the same instance (which is otherwise underspecified, just like the allocation itself). https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1353: and the type parameters of the immediately enclosing class bound to a set of actual type arguments $V_1, \ldots , V_m$. The binding of value parameters are specified elsewhere, but the type parameters seem to be unspecified. Where is the location where we can say that the type parameters are taken from the instance creation expression (or from some arguments to a reflective instance creation operation)? https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1358: No need for two empty lines: No new sections here. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1370: %First, a fresh instance (\ref{generativeConstructors}) $i$ of the immediately enclosing class is allocated. So here's the answer to the question "where does it get allocated in the first place?", but the '%' explains why we can't find it by searching the generated PDF. If we never mention it then we won't get in trouble with multiple unwanted occurrences of the allocation. Otherwise, making it part of the execution of a generative constructor makes it pop up below: 'the super constructor call .. is now executed', i.e., we'll perform allocation many times, each time of the enclosing class of that constructor. Or we need to say "by the way, _those_ constructor executions do not involve allocation of a fresh instance, they'll continue to work on the one we created in the "original" constructor execution". In order to clean up this issue, we could choose to make the allocation a completely separate action, with no connection to the execution of a generative constructor. It could be a side effect of the evaluation of a `new` expression. In that case there is no conflict between "executing a constructor with and without allocation". We still don't really know what it means to allocate a fresh instance of a given class because, as is the traditional C++ point of view, which makes sense here, too: the 'fresh instance' is just a memory area, it's not yet an instance of any class. So we would then need to talk about the size of instances of a class, at least as "something that is defined" even if we don't want to specify how to compute the exact size. I believe that new instances are _only_ allocated during evaluation of `new` expressions and as part of reflective constructor invocation. Given that reflection is described only briefly in the specification, we should be OK as long as we just mention the allocation with `new`. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1375: and the instance variable $v$ of $i$ is bound to $o$. OK, so this is now uncommented, and that's an improvement because it used to be omitted (I couldn't find any other location about it, at least). I guess the 'compile-time constant' stuff was very old.. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1377: %Next, a We might as well delete this line. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1382: in the order they appear in the program. This sounds like we'll evaluate the initializing expressions in the declaration first, then the ones in the initializer lists, and possibly initializing `final` fields twice, or just ignoring one of the values. The tools do not agree: `dart2js` says 'Field 'x' is initialized more than once.' and stops with a compile-time error. The vm is happy about the program, runs the declaration initializer once and the one in the initializer list twice, and then says 'Class 'C' has no instance setter 'x=''. ;-) So we should make a decision and specify it here. I created an issue for that discussion. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1389: otherwise all such variables are initialized with the \NULL{} value. We should strive to specify each property only once, and otherwise refer to the place where it is already specified: 'Then, for each instance variable $v$ of $i$ declared by the immediately enclosing class which is not yet bound to a value, it is a dynamic error if $v$ is \FINAL{}. \commentary{For the remaining (non-\FINAL{}) variables, the initial value is \NULL{} (\ref{variables}).}' https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1391: After this, unless the enclosing class is \code{Object}, the super constructor call implicitly or explicitly specified in $k$'s initializers, is now executed to further initialize $i$, as specified below. This is the place where it really helps to mention $i$! I believe the most direct form, using the existing specification of the superinitializer would be something like this: 'Then, unless the enclosing class is \code{Object}, the explicitly specified or implicitly added superinitializer (\ref{initializerLists}) is executed to further initialize $i$.' We will get the binding of `\THIS{}` recursively by just saying that we execute that superinitializer, but we do not specify the implicitly passed type parameters. This is one of the locations where that should be specified (for instance, declarations like `class D<X, Y> extends C<int, Y, List<X>> ..` illustrate that there is something to say). https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1395: It is not equivalent to moving the super call to the end of the initializers Seems more clear to use 'initializer list', because it's obvious how to understand the end of a list (otherwise, we might append it to each initializer ;-). https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1401: After all superclass constructors have completed, the body of $k$ is executed in a scope where \THIS{} is bound to $i$. I believe we should say 'After the superinitializer has completed' in order to avoid introducing the notion of 'superclass constructors' in normative text. It follows from the wording above that the execution of one superinitializer includes recursive invocation of the rest, up to `Object`. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1408: Execution of an initializer of the form \code{\THIS{}.$v$ = $e$} to initialize an object $i$ proceeds as follows: It's probably simpler if we avoid introducing yet another concept ("executing an initializer to initialize an object"), but we could say: 'During the execution of a generative constructor to initialize an instance $i$, execution of an initializer ..'. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1427: This evaluated argument list is remembered until after the entire initializer list has been evaluated, at which point the constructor is executed as follows: I'd prefer avoiding to introduce 'remember' as a normative concept. We could say that the argument list 'is evaluated, yielding a set of bindings $B$.' The specification uses phrases like 'bindings that resulted from the evaluation of the argument list' many times, but that is of course ill-defined because it takes both an actual argument list and a formal parameter list to provide the information that goes into a set of bindings (if we ignore the formal parameter list then we cannot bind an actual argument value to the proper name which is required for the body to be able to use that argument). But let's fix that in a separate CL, and then use the "usual" imprecise phrase here. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1433: The generative constructor $S$ (respectively $S.id$) of $S$ is executed to initialize $i$ with respect to the bindings that resulted from the evaluation of the argument list, and the type parameters (if any) of class $S$ bound to the current bindings of $U_1, , \ldots, U_m$. '..with respect to the bindings $B$, and the type parameters..' This falsely specifies that we use the same type arguments for the constructor $S$/$S.id$ as we did for the current constructor. In reality, we need to transform the type arguments as implied by the `extends` clause (for instance, with `classC<E> extends B<List<E>> ..` and `class B<F> ..`, we need to transform `E --> U` to `F --> List<U>`). https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:2383: at that point and throws the same exception. Aha, here is the congruence rule! (I was waiting for that when I saw '$e$ is evaluated to an object $o$' in line 1411). However, I'd prefer to introduce completion immediately, in order to keep closely related concepts together at their introduction. Maybe the following could be used: 'An {\em expression} is a fragment of Dart code that can be evaluated at run time. The evaluation may {\em complete with a value}, which is always an object, or it may {\em complete with an exception}, which amounts to {\em throwing an object and a stack trace}. Every expression has an associated static type (\ref{staticTypes}). Every value has an associated dynamic type (\ref{dynamicTypeSystem}). We need to introduce a general rule to specify propagation of exceptions in expression evaluation: Whenever the evaluation of an expression $e$ is specified to include evaluation of a set of subexpressions $e_1\ldots{}e_k$ in that order, if the subexpression $e_i$ is evaluated and completes with an exception throwing the object $o$ and the stack trace $s$, $e$ itself completes by throwing $o$ and $s$, without evaluating the remaining subexpressions $e_{i+1}\ldots{}e_k$, if any.' We don't even need to say 'if nothing else is stated' here, because `try` is a statement, not an expression. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:2384: Typo: Spurious empty line. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3097: There is no requirement that the expression $e$ evaluate to a special kind of exception or error object. Maybe add this, because the reader might consider this case to be tricky: 'The evaluation of $e$ may complete with a value $v$ or with an exception, but the latter is handled by the general rule about exception propagation (\ref{expressions}).' https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3101: If $e$ evaluates to \NULL{} (\ref{null}), then a \code{NullThrownError} is thrown. Otherwise let $t$ be a stack trace corresponding to the current execution state, and the \THROW{} statement aborts by {\em throwing} with $e$ as exception object and $t$ as stack trace. We might as well have a newline per sentence here. For the second sentence, the following would follow the terminology I suggested earlier more closely: 'Otherwise, the \THROW{} statement completes with an exception, throwing the value $v$ and a stack trace that corresponds to the current execution state.' I removed the `\em` on throwing because that word has been introduced earlier (and 'throwing' is something that happens both at `throw` and later at propagation, so it's not unnatural to tie it up to the general introduction of expression evaluation, where it is needed anyway). https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3108: } I think this text should remain normative (interpreting it as a new version of the sentence previously in line 3083). https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3377: \commentary{Note that it this point we are assured that the number of actual type arguments match the number of formal type parameters.} Could fix typo: 'at this point'. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3380: A fresh instance (\ref{generativeConstructors}), $i$, of class $R$ is allocated. Aha, so we should definitely simply delete the commented-out sentence in line 1370! Then we _do_ have that approach where `new` does the allocation, and constructors have nothing to do with that. It's _really_ nice to have the initializer stuff in the right place now! https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3381: Then $q$ is executed to initialize $i$ with its formal parameters bound to the evaluated argument list and, if $R$ is a generic class, with its type parameters bound to $V_1 \ldots V_m$. The binding stuff is still a mess, but this is probably safer: '.. with the formal parameter bindings that resulted from the evaluation of the argument list ..'. If we make sure that formal parameter binding operations always refer to 'bindings' then it's easier to find & fix this issue later on. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3383: If execution of $q$ completes normally, $e$ evaluates to $i$. This is a very special situation, because we cannot say that $q$ completes normally 'with the value $o$'. This means that the congruence rule in the comment on line 2383 does not apply directly (because there is no constructor invocation _expression_). So I'd suggest that we make it explicit here: 'If execution of $q$ completes normally then the evaluation of $e$ completes normally with the value $i$; if it completes with an exception then the evaluation of $e$ completes with the same exception.' https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3392: % Used to not have the "in-between" clause, which would disallow a factory constructor redirecting to another constructor which conditionally calls the original factory constructor again with different arguments. Reword to work for the general case, not just this situation where it motivates an update ('We cannot make every cyclic execution an error because ..'). https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3396: Otherwise, the body of $q$ is executed with respect to the bindings that resulted from the evaluation of the argument list and the type parameters (if any) of $q$ bound to the actual type arguments $V_1, \ldots, V_l$. We definitely need to have a comma here: '..argument list, and..'. Actually: '..argument list, and with the type parameters..' would work better, because then we have 'with respect to .. bindings' and 'with type parameters .. bound'. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3399: The result of the evaluation of $e$ is $i$. Isn't a factory constructor a function that returns a value? Certainly, \ref{factories} uses phrases like 'the return type of a factory' and 'a factory returns'. Then why not just stick to 'If this execution completes with the returned value $o$ then the evaluation of $e$ completes normally with the value $o$; if it completes with an exception, evaluation of $e$ completes with the same exception'. The reason for including both types of completion is the same as previously: We hit a generative constructor, so the general propagation rule for expressions doesn't apply (a similar rule for statements wouldn't apply, either). (To 'complete with returned value' is introduced below.) https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3563: If $f$ is marked \ASYNC{} (\ref{functions}), then a fresh instance (\ref{generativeConstructors}) $o$ implementing the built-in class \code{Future} is associated with the invocation and immediately returned to the caller. The body of $f$ is scheduled for execution at some future time. The future $o$ will complete when execution of $f$ completes (\ref{completion}). If $f$ completes by {\em returning} a value, that value used to complete $o$, if it {\em completes normally} or by {\em returning} with no value, $o$ is completed with \NULL{}, and if it completes by {\em throwing} an exception $e$ and stack trace $t$, $o$ is completed with $e$ and stack trace $t$ as an error. I'd suggest that we avoid the concept of completing without a value. Implementations (`dart2js` and `dart`) agree that `void f() { return; }` and `void g() {}` both return `null` dynamically, and we discussed returning whatever-you-want in a `void` function, so we are well-situated to simply declare that there is a return value in all cases. So we could do this: '.. If the execution of the body of $f$ completes normally with the value $v$ then the future $o$ completes to $v$; if it completes with an exception then the future $o$ will complete to the same exception.' I searched a bit for the terminology used with future completion, and 'complete to' seems to exhibit a reasonably clear difference to 'complete with' that we've used for expressions and now functions. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3568: \item If $f$ {\em completes normally}, then if $s$ has been canceled then its cancellation future is completed with \NULL{} (\ref{null}). I think we should reserve `{\em ..}` for introductory occurrences of terms (or non-normative text where ordinary textual emphasis may be useful). In this case, 'completes normally' is not introduced. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3569: \item If $f$ {\em throws} exception $e$ and stack trace $t$: Keeping the usual phrases for this, we would have 'If $f$ completes with an exception throwing the object $o$ and stack trace $t$:' https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3572: \item If $s$ has been canceled then its cancellation future is completed with $e$ and $t$ as an error. $e$ would now be $o$, twice. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3602: \item If $f$ {\em completes normally}, $j$ is positioned after its last element, so that its current value is \NULL{} and the current call to \code{moveNext()} on $j$ returns false, as will all further calls. 'If $f$ completes normally with the value $v$, $v$ is ignored and $j$ is positioned after..'. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3603: \item If $f$ {\em throws} exception $e$ and stack trace $t$ then the current value is \NULL{} and the current call to \code{moveNext()} throws $e$ and $t$ as well. Further calls must return false. 'If $f$ completes with an exception then a call to \code{moveNext()} must complete with the same exception, and the current value must be \NULL{}. Further calls to \code{moveNext()} must return false.' I guesstimated that the further calls would be to `moveNext()`, but since that wasn't immediately obvious I think we should make it explicit. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3628: If $f$ completes by {\em throwing}, the invoking call expression throws the same exception object and stack trace. Following the same style we would have something like this (I replaced 'when' by 'if' because it may not terminate at all): 'If the execution of the body of $f$ completes (\ref{completion}) normally with a value $v$ then the function invocation completes normally with the value $v$. If the execution of the body of $f$ ends because the last statement has completed normally, the function invocation completes normally with the value \NULL{}. If the execution of the body of $f$ completes with an exception throwing the object $o$ and stack trace $s$, the function invocation completes with the same exception $(o, s)$.' https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3637: expression can represent the behavior of a function body. I know this is commentary, but I think there are too many `\em`s, and there are also a couple of other issues. Here's a possible revision: 'A function invocation can never abort at \BREAK{} or \CONTINUE{} because it is a compile-time error for these statements to occur anywhere else than inside an enclosing statement $S$ that handles them. This is either because $S$ is a labelled statement with the same label, or because the given \BREAK{} or \CONTINUE{} does not have an associated label, and $S$ is a \SWITCH{} statement or a loop. This means that the only possible ways for the execution of the body of a function to end is (1) completing normally with a value, and (2) completing with an exception. This is a set of completion modes that expressions support, so it can be directly transferred to the function invocation.' https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:5041: If $e$ evaluates to an object $o$ that is not an instance of \code{Future}, then let $f$ be the result of creating a new object using the constructor \code{Future.value()} with $o$ as its argument; otherwise let $f$ be the result of evaluating $e$. I'd prefer if we keep all completion situations explicit, because we need to make it very easy to discover the locations where the exception propagation applies. Here's a possible way to do that: 'If the evaluation of $e$ completes normally with a value $o$ which is not an instance of \code{Future} then ..[same]..; otherwise let $f$ be $o$.' https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:5044: Next, the stream associated with the innermost enclosing asynchronous for loop (\ref{asynchronousFor-in}), if any, is paused. Execution of the function $m$ immediately enclosing $a$ is suspended until after $f$ completes. At some time after $f$ is completed, control returns to the current invocation. If $f$ has completed with an exception $x$ and stack trace $t$, $a$ {\em throws} $x$ and $t$. If $f$ completes with a value $v$, $a$ evaluates to $v$. OK, we discussed a while back how to interleave these suspend/pause events. I'll leave it to others to have strong opinions about it and just note that it is being done here. However, it would be useful to make sure that the change is documented in a dart-lang-evolution issue -- which may or may not be the case already, but I couldn't immediately spot it. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:5456: \LMLabel{statements} Missing empty line, then missing `\LMHash{}` for the next paragraph. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:5457: A {\em statement} is a fragment of Dart code that can be executed at runtime. Statements, unlike expressions, do not evaluate to a value, but are instead executed for their effect on the program state. It's a smart phrase, 'Statements, unlike expressions, do not..' but it still seems twisted. Maybe a small change to 'Unlike expressions, statements do not..' would make it more smooth to read. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:5458: Some statements can affect control flow, in particular \BREAK{}, \CONTINUE{}, \RETURN{} and \THROW{} statements. Function invocations do affect the control flow as well, even though they'll (often) return to "nearly the same spot". Logical operators with short-cut semantics affect the control flow as well, as do loops etc. So we definitely need to admit that the listed statements aren't the only ones. But maybe they are the only ones that work like a structural variant of regular GOTO statements? Maybe they are special in that they affect the control flow by jumping to something which is _not inside_ the construct itself. We could then say 'Some statements can affect control flow in a way that isn't confined to the statement itself, in particular..', which still lets `?:`, `switch` etc. do their thing without forcing us to mention them here. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:5460: \LMLabel{completion} It breaks the rules to have an \LMLabel{} which is anywhere else than immediately after a sectioning command. That's because it produces a label that refers to the "current number", which is otherwise the number of the section as shown in the \tableofcontents and used in all the occurrences of `(\ref{whatever})`. So in this case it would just cause `\ref{completion}` to work exactly like \ref{statements}. So we need to introduce a new section/subsection/.. in order to have something to refer to. This would make sense anyway, because completion occurs all over the place. That subsection would then refer to the (beginning) of the sections \ref{statements} and \ref{expressions} etc., wherever we have something about completion, after giving a brief introduction to the underlying ideas. This location would then just have the normal \LMHash{} for each normative paragraph. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:5461: Execution of a statement can {\em complete} in two ways: either it {\em completes normally} or it {\em aborts}. It can {\em abort} in one of four ways: Either it {\em breaks} or it {\em continues} (either to a label or without a label), it {\em returns}, either with a value or without one, or it {\em throws} an exception object and an associated stack trace. It is tempting to use these short-hands, but I still think it would be useful to strictly make completion explicit. We could do it like this: 'Execution of a statement can {\em complete} in several ways, also known as {\em completion modes}: \begin{itemize} \item It can {\em complete normally}. \item It {\em complete with a \BREAK{}} or {\em with a \CONTINUE{}}, optionally {\em to a label}. \item It can {\em complete with a returned value}. \item It can {\em complete with an exception}, which amounts to {\em throwing an object and a stack trace}. \end{itemize} In all cases except normal completion, we say that the statement {\em completed by aborting} or that it {\em aborted}. \commentary{ Note that aborted execution does not imply that anything went wrong, it just means that execution continues somewhere else than the next statement. }' As usual, I've put the emphasis on making 'complete' explicit, and I've reserved two levels of detail for the exception: The exception as two named entities (both an object thrown and a stack trace captured) and the two parts as a whole (when we don't need to talk about the parts). https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:5477: at that point and throws the same exception object and stack trace. I'm not so happy about introducing any 'default' mechanisms here, or about placing examples in normative text. I think we can avoid this using the same style as with expressions (so this is a proposal for text that replaces all of lines 5463-5477): 'We need to introduce a general rule to specify propagation of completion modes in statement execution: Whenever the execution of a statement $S$ is specified to include execution of a set of immediately enclosed statements $S_1\ldots{}S_k$, if the statement $S_i$ is executed and aborts then $S$ aborts in the same way. Whenever the execution of $S$ is specified to include the evaluation of an immediately enclosed expression $e$, if this evaluation completes with an exception then $S$ completes with the same exception. This rule does not apply in all cases, but every exception to the rule is specified explicitly. \commentary{ For instance, if the body of a loop completes with a \BREAK{} without a label then that loop will complete normally, rather than propagating the breaking completion. }' https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:5479: \LMHash{} We haven't otherwise used \LMHash{} markers on grammar blocks, so I'd suggest that we keep putting \LMHash{} on natural language paragraphs, and only there. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:5525: Just for consistency, let's keep 2 empty lines before sections. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:5751: then the statement is treated as if it had completed normally. 'If this execution completes with a \BREAK{}, without a label or with a label that this \FOR{} statement is labeled with (\ref{labels}), then the \FOR{} statement completes normally. If this execution completes with a \CONTINUE{}, without a label or with a label that this \FOR{} statement is labeled with, then the execution of this \FOR{} statement continues at step \ref{beginIteration}.' https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:5753: execution of the for loop stops and aborts in the same way. ' \commentary{ If it aborts in any other way then the \FOR{} statement aborts in the same way, following the general propagation rule. For instance, it could complete with a returned value or with an exception. }'
Lots of comments. PS, for other reviewers: Finally Lasse an I agree on a terminology for completion modes that seems to be reasonably readable and also recognizable as talking about completion: There should be a reference `(\ref{completion})` immediately after each phrase that talks about completion, strictly in the cases where no variant of the word `complete` is used and typically even when it is used. This means that we can have `the execution continues (\ref{completion})` and `the evaluation breaks with a label .. (\ref{completion})` and similar things, explicitly indicating that it doesn't mean something like "the execution continues [at line 117]" or "the evaluation breaks [the invariant]" or similar things that would otherwise be a natural parsing of an innocent-looking word like 'continues' or 'breaks'. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... File docs/language/dartLangSpec.tex (right): https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:2651: An {\em integer literal} is either a hexadecimal integer literal or a decimal integer literal. Invoking the getter \code{runtimeType} on an integer literal returns the \code{Type} object that is the value of the expression \code{int}. The static type of an integer literal is \code{int}. I actually think the spec carefully tries to _avoid_ imposing itself on the libraries here! ;) The spec needs to specify the syntax and semantics of Dart programs, so in particular it needs to specify all possible syntactic expressions including `int` literals. They need to have a static type. It would be possible to omit the information about its dynamic type, but we wouldn't want to have an implementation where `42` evaluates to a list or a future, so that bit is there to rule out crazy stuff: We require every implementation to behave in such a manner that integer literals evaluate to instances of `int`, and then it's up to the standard libraries to define all the properties that such `int` values have. The reference to `runtimeType` looks messy because that method may in general be overridden, but the spec, \section{Overview}, states that 'The run-time type of every object is represented as an instance of class \code{Type} which can be obtained by calling the getter \code{runtimeType}..', which means that the spec _intends_ `runtimeType` to deliver the actual runtime type. We may wish to reword that everywhere (and we may wish to have a different kind of support for obtaining the runtime type of an object that cannot be overridden), but let's just accept for now that this is how the spec says "the runtime type of an object". With that, it is _not_ necessary to say that the runtime type of an integer value is `int`: That just states or confirms the meaning of "integer value", i.e., that it is an instance of `int`; and such an entity must return the value of the expression `int` as its dynamic type. My conclusion is: We should say that integer literals have that dynamic type (needed to avoid crazy stuff), but not that integer values have that dynamic type (redundant), so the wording is OK as it is today. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5805: Execution of a for-in statement, $f$, of the form \code{\AWAIT{} \FOR{} (finalConstVarOrType? id \IN{} $e$) $s$} proceeds as follows: We do have a couple of occurrences of `id` as a meta-variable occurring in a `\code{..}` context (rather than math mode as in `$id$`). However, these cases are clearly the exception (and some of them seem to be motivated by being in a non-normative context, where the use of math mode clashes with plain italic to make everything look like regular text). In this context we already have $e$ and $s$, and there are lots of similar elements saying "syntactic meta-symbols use math mode". It is a bit messy to use multi-letter symbols in math mode, but `id` isn't that bad (something like $buffer$ is much worse because of the big difference between $f$ and \itshape{f}), and we also have $type$, $inherited$, $overrides$, and more. So I'd suggest that we use $id$. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5813: The stream $o$ is listened to, producing a stream subscription $u$, Yes, thank you! The spec mentions stream subscriptions a few times, but they haven't been introduced anywhere. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5816: This allows other asynchronous events to execute while this loop is waiting for stream events. This sentence should not be normative, but it might work well as a \rationale{}. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5823: If the subscription is already paused, the \code{pause} call may be omitted. I think it gets too difficult to distinguish commentary and normative text if they occur together (the font difference doesn't scream it out). I did find exceptions (and I was surprised to find them), but it is very nearly consistently enforced that commentary is put into its own paragraph. I'd prefer if we maintain that style. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5827: the statement $s$ is executed with \code{id} bound to the value of the current data event. \code{id} --> $id$ https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5830: If another event $e_u$ of $u$ occurs before execution of $s$ is complete, handling of $e_u$ must wait until $s$ is complete. This could be commentary, but for normative text we otherwise have a style where actions are described, not constraints on actions that "must wait" or anything like that. (Basically, we don't usually tolerate normative language which is so far removed from a "typical" intended implementation). Is there an operational way to specify the same behavior? https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5833: If execution of $s$ {\em continues} with no label, or with a label that prefixes the asynchronous for statement (\ref{labels}), then the execution of $s$ is treated as if it had completed normally. I still think that it's messy to add `{\em ..}` in order to point out that the word `continues` is special. Surely lots of people will still read it to mean simply that "the execution continues", and then they'll get really confused. The messy bit is that italic is otherwise used in normative text to indicate that a particular occurrence of a word is the defining occurrence. People know that this is what they need to find in order to get to know what that word means. Update after lunch: Let's use these words (throws, continues, throwing, continuing, and similar forms) without an explicit `completes`, but then _rigidly_ follow the scheme that they must be followed by `(\ref{completion})`. I think that will be sufficient to ensure that even `if execution .. continues` can be parsed correctly by the reader. Woo-hoo! https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5845: until $u$ is no longer paused. Couldn't we mandate the interpretation that '$u$ is resumed' must resume $u$, and it is an implementation dependent property that some stream subscriptions will need multiple invocations of \code{resume}? (That is, couldn't we just remove that sentence?) https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5888: If that execution completes normally or it {\em continues} with no label or with a label that prefixes the \WHILE{} statement (\ref{labels}), then the while statement is re-executed. New style: 'completes normally or it continues with no label (\ref{labels}) or with a label that prefixes the \WHILE{} statement (\ref{completion}),` https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5890: If $r$ is \FALSE{}, then execution of the while statement completes normally. +` (\ref{completion})` https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5914: If that execution {\em continues} with no label, or with a label that prefixes the do statement (\ref{labels}), then the execution of $s$ is treated as if it had completed normally. The usual stuff: `If that execution continues with no label (\ref{labels}) or with a label that prefixes the do statement (\ref{completion}),` I would prefer `\DO{} statement` in order to avoid phrases where the words referring to syntax may be misinterpreted as "normal" words, but I can see that other locations also use `do statement` and `while statement` and similar stuff. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5917: Then, the expression $e$ is evaluated to an object $o$. Then, $o$ is subjected to boolean conversion (\ref{booleanConversion}), producing an object $r$. If $r$ is \FALSE{}, execution of the do statement completes normally. +` (\ref{completion})` https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6018: Next, the case clause \CASE{} $e_{1}: s_{1}$ is matched against {\code id} if it exists. If \CASE{} $e_{1}: s_{1}$ does not exist, then if there is a \DEFAULT{} clause, its statements, if any, are executed (\ref{case-execute}). On 2016/10/13 12:18:37, Kevin Millikin (Google) wrote: > It sounds like id might not exist. I would say something like: if the case > clause ... exists it is matched against v. I suggested switching the order, which would handle that issue as well: `Next, $id$ is matched against the case clause \CASE{} $e_{1}: s_{1}$, if it exists. Otherwise, the statements $s_{n+1}$ of the \DEFAULT{} case are executed, if there is a \DEFAULT{} case. Otherwise, the switch statements completes normally (\ref{completion}).` https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6039: If $v$ is not \TRUE{} the following case, \CASE{} $e_{k+1}: s_{k+1}$ is matched against {\code id} if it exists. If \CASE{} $e_{k+1}: s_{k+1}$ does not exist, then the \DEFAULT{} clause's statements are executed (\ref{case-execute}). On 2016/10/17 10:08:23, Lasse Reichstein Nielsen wrote: > On 2016/10/13 12:18:36, Kevin Millikin (Google) wrote: > > Again, it sounds like id might not exist. > > Done. I'd suggest a similar rewrite as the previous one (but I can't see the result of 'Done' anywhere, so it may have happened already). https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... File docs/language/dartLangSpec.tex (right): https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5777: or {\em continues} with a label that prefixes this \FOR{} statement (\ref{labels}), Following the newest plan (around noon, Oct 19), this would not have the {\em..} around completion related words, but it would have (\ref{completion}) after the completion related phrase. We could put it 3 times, but maybe this will suffice (because we have `continues` so close to `with.. a label` everywhere): `If this execution completes normally, continues without a label, or continues with a label (\label{labels}) that prefixes this \FOR{} statement (\ref{completion})` https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5879: On the first {\em error event} from $u$, We shouldn't specify 'first': Saying that something must happen in a given specification may have as a "lemma" (a necessary consequence) that this must be the first error event, but if we wish to make this explicit it would be commentary. The normative text shouldn't mention necessary consequences (it's redundant). Also, an "error event from $u$" seems imprecise, how does such an event arise, or how is it detected? https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5913: Please insert \LMHash{} or delete the empty line. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5915: If that execution {\em completes normally} or it {\em continues} with no label or with a label that prefixes the \WHILE{} statement (\ref{labels}), then the while statement is re-executed. Should cover the situation where $s$ completes with a break. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6040: The statement \code{\VAR{} id = $e$;} is evaluated, where \code{id} is a variable whose name is distinct from any other variable in the program. In checked mode, it is a run time error if the value of $e$ is not an instance of the same class as the constants $e_1 \ldots e_n$. `id` --> `$id$` in the statement, `\code{id}` --> `$id$` otherwise. We already have many occurrences of `fresh variable` in the spec, so we could reduce `a variable whose name is distinct from any other variable in the program` to that. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6045: Next, the case clause \CASE{} $e_{1}: s_{1}$ is matched against {\code id} if such a case clause exists. If \CASE{} $e_{1}: s_{1}$ does not exist, then if there is a \DEFAULT{} clause, its statements, if any, are executed (\ref{case-execute}). We did introduce $s_{n+1}$ a few lines earlier, so the issue is not whether \DEFAULT{} has any statements, it's whether there is a \DEFAULT{} clause at all. I'd prefer this: `.. if there is a \DEFAULT{} clause, its statements $s_{n+1}$ are executed`. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6048: Matching of a \CASE{} clause \CASE{} $e_{k}: s_{k}$ of a switch statement Why did the scope sentence go away? Surely we don't want to break all the code that puts declarations into a `case`? https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6059: against a value {\code id} proceeds as follows: `{\code id}` --> `$id$`. I actually think the following text reads better if we use the opposite ordering: Put 'Matching of a value $id$ against a \CASE{} clause \CASE{} $e_k: s_k$ of a switch statement' before the code environment, and then just 'proceeds as follows:' here. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6062: The expression \code{$e_k$ == id} is evaluated to an object $o$ which is then subjected to boolean conversion producing a value $v$. 'id' --> '$id$'. In this CL we had things like 'An {\em expression} is a fragment of Dart code that can be evaluated at run time to yield a {\em value}', and 'yield' is used in at least dozens of cases in this way in the spec. With 'produce' I could only find two examples where the thing 'produced' is the result of computations: That's when constructors 'produce' an object. In that case it is already an exception because that's not expression evaluation, it is "procedure invocation" following the primitive allocation which is associated with `new`. So please keep `yielding` here. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6063: If $v$ is not \TRUE{} the following case, \CASE{} $e_{k+1}: s_{k+1}$ is matched against {\code id} if such a case clause exists. If \CASE{} $e_{k+1}: s_{k+1}$ does not exist, then the \DEFAULT{} clause's statements are executed (\ref{case-execute}). 'If $v$ is not \TRUE{}, $id$ is matched against the following case, \CASE{} $e_{k+1}: s_{k+1}$, if it exists; otherwise the default statements $s_{n+1}$ are executed.' I'm not sure why there should be a reference \ref{case-execute}, because the default case has no matching, it's only about execution of ordinary statements. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6080: The expression \code{$e_k$ == id} is evaluated to an object $o$ which is then subjected to boolean conversion producing a value $v$. Keep `yielding`. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6081: If $v$ is not \code{true} the following case, \CASE{} $e_{k+1}: s_{k+1}$ is matched against {\code id} if it exists. We have no existing occurrences of `\code{true}`, and the spec has the following at the beginning of \subsection{Booleans}: `The reserved words \TRUE{} and \FALSE{} denote objects that represent the boolean values true and false respectively.` So we already use the plain words true and false (no special formatting) for the value yielded by an evaluation of \TRUE{} and \FALSE{}. So this could be as follows: 'If $v$ is not true, $id$ is matched against the following case \CASE{} $e_{k+1}: s_{k+1}$; otherwise, the switch statement completes normally.' https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6082: If $v$ is \code{true}, let $h$ be the smallest integer such that $h \ge k$ and $s_h$ is non-empty. If no such $h$ exists, let $h$ be $n$. The sequence of statements $s_h$ is executed (\ref{case-execute}). '\code{true}' --> 'true', drop the \ref. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6117: \subsubsection{ Switch case statements} Argh, we don't have to have that weird space ('{ S') in _new_ material! https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6119: Execution of the statements $s_h$ of a switch statement Please add empty line and `\LMHash{}` in front of normative paragraph. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6159: execution of the switch statement continues with the case labeled by that label. This again shows that 'execution continues' is too smart to work really well, because we will (1) need to very carefully avoid saying 'execution continues' in the normal sense; and I'm not convinced that it is enough to use the magic `{\em continues}` for the completion mode. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6164: It's hard to tell which is better, but we should consider the alternatives: Either we'd specify that the execution runs `s_h; throw <something>`, or we'd spell out how to get the same effect without the code. In order to maintain compositionality we should of course never execute manipulated code ;-) but the description given here illustrates how much more index manipulation it takes to use this alternative. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6224: A set of \ON{}-\CATCH{} clauses, each of which specifies (either explicitly or implicitly) the type of exception object to be handled, two exception parameters and a block statement. We still need to textually allow the omission of the stack trace parameter, just like the grammar rule says, right? https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6237: An \ON{}-\CATCH{} clause of the form \code{\ON{} $T$ \CATCH{} ($p_1$) $s$} is equivalent to an \ON{}-\CATCH{} clause \code{\ON{} $T$ \CATCH{} ($p_1, p_2$) $s$} where $p_2$ is an identifier that does not occur anywhere else in the program. We have 12 occurrences of `fresh variable` and only two (until now) of identifier-or-variable that `does not occur`, so we might as well use `fresh variable` everywhere in new material. We should then make sure that it is defined once and for all, possibly in \section{Overview}. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6240: An \ON{}-\CATCH{} clause of the form \code{\ON{} $T$ $s$} is equivalent to an \ON{}-\CATCH{} clause \code{\ON{} $T$ \CATCH{} ($p_1, p_2$) $s$} where $p_1$ and $p_2$ are identifiers that do not occur anywhere else in the program. `fresh variable` https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6243: An \ON{}-\CATCH{} clause of the form \code{\CATCH{} ($p$) $s$} is equivalent to an \ON{}-\CATCH{} clause \code{\ON{} \DYNAMIC{} \CATCH{} ($p$, $p_2$) $s$} where $p_2$ is an identifier that does not occur anywhere else in the program. `fresh variable` https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6264: If execution of $b$ {\em throws} (\ref{completion}) with exception object $e$ and stack trace $t$, then $e$ and $t$ are matched against the \ON{}-\CATCH{} clauses to yield a new completion (\ref{on-catch}). Just 'throws'. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6270: Otherwise if execution of $b$ threw, the \TRY{} statement completes in the same way as the matching against the \ON{}-\CATCH{} clauses. `threw (\ref{completion})` https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6273: \subsubsection{\ON{}-\CATCH{} clauses} `\LMLabel{..}`, empty line. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6280: \end{dartCode} +`proceeds as follows:`, and no colon after `form` above. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6283: If there are no \ON{}-\CATCH{} clauses ($n = 0$), matching completes by {\em throwing} the exception object $e$ and stack trace $t$. `completes by throwing (\ref{completion})` https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6286: \LMHash{} Move `LMHash` up in front of the paragraph, and add one just before the next one. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6290: It is of course a static warning if $T_i$, $1 \le i \le n$ is a deferred or malformed type. Delete 'of course' and move this sentence up a few lines to a context where the `try` statement is discussed as a whole. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6304: Wow, that's a substantial improvement! Was the semantics of canceling stream subscriptions of enclosing await-for statements preserved by adding the same thing to them based on the completion mode of its body? Also, is it an improvement that the spec says nothing about stack traces any more? Or is there something elsewhere? I couldn't find it based on a few naive searches. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6324: Then the return statement completes by \em{returning} the value $o$ (\ref{completion}). The `\em{..}` construct makes a zero-argument command like `\em` leak into the enclosing text (so lots of stuff will now be \em'd. As usual, I'd suggest: `completes by returning..`. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6332: \LMHash{} Why did the ASYNC / wrong-return-type error paragraph go away? Is that because \section{functionInvocation} says what needs to be said for this? A quick check did not reveal that this has happened, shouldn't it be added around line 3600? https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6361: Executing a return statement with no expression, \code{\RETURN;} {\em returns} with no value (\ref{completion}). I'd still prefer `returns with the value null (\ref{completion}).`, to make it work as implemented and as-expected-in-the-future in order to make it well-defined what happens if the value returned from a `void` function gets used (because the type checker couldn't see it coming). https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6390: The namespace of labels is distinct from the one used for types, functions and variables. Prepend `LMHash{}` to new paragraph. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6415: Execution of a \BREAK{} statement \code{\BREAK{} label;} completes by {\em breaking} with the label \code{label} (\ref{completion}). `{\em breaking}` --> `breaking`. We have the same issue here is before with `id`: It ought to be $label$, unless that is too unreadable. If it looks bad then we can use `\mbox{\em label}`, which will work in a math context and produce reasonable kerning. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6417: Execution of a \BREAK{} statement \code{\BREAK{};} completes by {\em breaking} without a label (\ref{completion}). `{\em breaking}` --> `breaking`. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6435: Execution of a \CONTINUE{} statement \code{\CONTINUE{} label;} completes by {\em continuing} with the label \code{label} (\ref{completion}). `continuing` https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6437: Execution of a \CONTINUE{} statement \code{\CONTINUE{};} completes by {\em continuing} without a label (\ref{completion}). `continuing` https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6465: If the enclosing function $m$ is marked \ASYNC* and the stream $u$ associated with $m$ has been canceled, then the \YIELD{} statement completes by {\em returning} \code{null} (\ref{completion}), otherwise it completes normally. `returning` https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6525: \item The getter \cd{current} is invoked on $i$. If the invocation {\em throws} an exception $ex$, execution of $s$ completes in the same way. Otherwise, the result $x$ of the getter invocation is added to the iterable associated with $m$. If I understand this right then `the invocation throws an exception $ex$ (\ref{completion})` should work. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6543: Then, if the cancel completed normally, the stream execution of $s$ {\em returns} with no value (\ref{completion}). `returns` https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6575: It is a dynamic type error if $o$ is not of type \code{bool} or of type \code{Function}, or if $r$ is not of type \code{bool}. If $r$ is \FALSE{}, we say that the assertion failed. If $r$ is \TRUE{}, we say that the assertion succeeded. If the assertion succeeded, execution of the assert statement is complete. If the assertion failed, the execution {\em throws} an \code{AssertionError} with a stack trace corresponding to the \ASSERT{} statement. `the execution throws .. to the current execution state at the \ASSERT{} statement (\ref{completion}).`
Initial comments https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.tex File docs/language/dartLangSpec.tex (right): https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1215: A {\em generative constructor} is executed to initialize a freshly allocated object. I want to say something here because it introduces a new mode of execution (execution to initialize a new object). This is similar to the text written about statements and expressions describing that they can be executed and evaluated respectively. A generative constructor can be "executed to initialize". That said, it's not saying much, so let's just drop it. As discussed, the allocation happens below. that's fine with me - the `new` operator allocates the object, the constructors initialize the new object. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1298: % Need to specify exactly how executing a redirecting constructor works I have removed these lines. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1351: Execution of a generative constructor $k$ to initialize a fresh instance $i$ On 2016/10/17 16:44:57, eernst wrote: > I think we need to preserve the information about the binding of `\THIS{}`. I don't think that's necessary here. The `this` is only in scope inside the body, and `this` is bound to $i$ there (line 1401). ... > (which is otherwise underspecified, just like the allocation itself). Allocation is specified in the `new` expression section. It's not part of the generative constructor semantics (so we can execute the super-constructor without allocating more objects), instead the generative constructor *initializes* the new object. If we ever make `new` optional, we probably have to add an initial allocation step to calling the constructor, separate from its initialization semantics. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1353: and the type parameters of the immediately enclosing class bound to a set of actual type arguments $V_1, \ldots , V_m$. The constructor $k$ is invoked on a type $T$. The $T$ may be a parameterized class type with type parameters. I guess I should add "of the type $T$" above after "generative constructor $k$". https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1358: On 2016/10/17 16:44:57, eernst wrote: > No need for two empty lines: No new sections here. Acknowledged. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1370: %First, a fresh instance (\ref{generativeConstructors}) $i$ of the immediately enclosing class is allocated. It *is* a side-effect of evaluating a `new` expression (line 3380). https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1375: and the instance variable $v$ of $i$ is bound to $o$. The initialization of fields were also done in the `new` operator, although not in a way that actually worked. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1377: %Next, a We could delete all the comments. A few might me relevant, but they are still in the git history. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1382: in the order they appear in the program. This only refers to the initializers in the initializer list. The ones for class fields are not initializers of $k$ and Initializing formals are not initializers, so the initializer list is the only thing left. Maybe it should be made more clear. Reworded. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1389: otherwise all such variables are initialized with the \NULL{} value. I don't see the rewrite as better than what's already there. That commentary would make it sound like the variables are already initialized with `null`, which they aren't. The way I have written it, all class fields are initialized at least once, and final fields exactly once. I treat "binding the variable to a value" as an imperative step. Before doing that binding, the variable has no binding. This distinguishes a variable with no binding from one with `null` as value. Moving the `null` value to a commentary basically leaves some fields unbound. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1395: It is not equivalent to moving the super call to the end of the initializers On 2016/10/17 16:44:57, eernst wrote: > Seems more clear to use 'initializer list', because it's obvious how to > understand the end of a list (otherwise, we might append it to each initializer > ;-). Acknowledged. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1397: which must happen in the order the expressions occour in the program text. On 2016/10/10 18:58:15, floitsch wrote: > occur Acknowledged. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1401: After all superclass constructors have completed, the body of $k$ is executed in a scope where \THIS{} is bound to $i$. Good point. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1408: Execution of an initializer of the form \code{\THIS{}.$v$ = $e$} to initialize an object $i$ proceeds as follows: ACK https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1427: This evaluated argument list is remembered until after the entire initializer list has been evaluated, at which point the constructor is executed as follows: On 2016/10/17 16:44:58, eernst wrote: > I'd prefer avoiding to introduce 'remember' as a normative concept. We could say > that the argument list 'is evaluated, yielding a set of bindings $B$.' I believe "binding" refers to the result of applying actual arguments to a formal parameter list. Here we only evaluate the actual arguments, we do not bind them yet (which is important, since the binding may contain initializing formals, and must happen after field initializers). > The specification uses phrases like 'bindings that resulted from the evaluation > of the argument list' many times, but that is of course ill-defined because it > takes both an actual argument list and a formal parameter list to provide the > information that goes into a set of bindings (if we ignore the formal parameter > list then we cannot bind an actual argument value to the proper name which is > required for the body to be able to use that argument). Exactly. > But let's fix that in a separate CL, and then use the "usual" imprecise phrase > here. I don't think it applies here, but I'll check if it would be no more wrong than other occurrences. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1433: The generative constructor $S$ (respectively $S.id$) of $S$ is executed to initialize $i$ with respect to the bindings that resulted from the evaluation of the argument list, and the type parameters (if any) of class $S$ bound to the current bindings of $U_1, , \ldots, U_m$. No, the U_1 .. U_m *are* the type parameters of the *superclas* as specified in the superclass/extends clause of the class declaration. That's what line 1430 says. At this point we remember the supertype (superclass plus type parameters), the construtor name and the constructor arguments. At a later point we execute that constructor of that type with those arguments to initialize $i$. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:2383: at that point and throws the same exception. On 2016/10/17 16:44:58, eernst wrote: > Aha, here is the congruence rule! (I was waiting for that when I saw '$e$ is > evaluated to an object $o$' in line 1411). > > However, I'd prefer to introduce completion immediately, in order to keep > closely related concepts together at their introduction. Maybe the following > could be used: > > 'An {\em expression} is a fragment of Dart code that can be evaluated at run > time. The evaluation may {\em complete with a value}, which is always an object, > or it may {\em complete with an exception}, which amounts to {\em throwing an > object and a stack trace}. > > Every expression has an associated static type (\ref{staticTypes}). Every value > has an associated dynamic type (\ref{dynamicTypeSystem}). > > We need to introduce a general rule to specify propagation of exceptions in > expression evaluation: Whenever the evaluation of an expression $e$ is specified > to include evaluation of a set of subexpressions $e_1\ldots{}e_k$ in that order, > if the subexpression $e_i$ is evaluated and completes with an exception throwing > the object $o$ and the stack trace $s$, $e$ itself completes by throwing $o$ and > $s$, without evaluating the remaining subexpressions $e_{i+1}\ldots{}e_k$, if > any.' > > We don't even need to say 'if nothing else is stated' here, because `try` is a > statement, not an expression. Acknowledged. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3097: There is no requirement that the expression $e$ evaluate to a special kind of exception or error object. On 2016/10/17 16:44:56, eernst wrote: > Maybe add this, because the reader might consider this case to be tricky: > > 'The evaluation of $e$ may complete with a value $v$ or with an exception, but > the latter is handled by the general rule about exception propagation > (\ref{expressions}).' Acknowledged. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3108: } The previous paragraph (which has since been rewritten) corresponds to line 3083, this is commentary explaining what that paragraph means. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3377: \commentary{Note that it this point we are assured that the number of actual type arguments match the number of formal type parameters.} On 2016/10/17 16:44:56, eernst wrote: > Could fix typo: 'at this point'. Done. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3380: A fresh instance (\ref{generativeConstructors}), $i$, of class $R$ is allocated. The allocation was always done here. Previously the field initialization was also done here, badly. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3381: Then $q$ is executed to initialize $i$ with its formal parameters bound to the evaluated argument list and, if $R$ is a generic class, with its type parameters bound to $V_1 \ldots V_m$. On 2016/10/17 16:44:57, eernst wrote: > The binding stuff is still a mess, but this is probably safer: > > '.. with the formal parameter bindings that resulted from the evaluation of the > argument list ..'. Again I don't think that applies because the actual binding happens later, after initializing fields, and it will handle initializing formals. Or maybe I'm wrong. I'll check :) > > If we make sure that formal parameter binding operations always refer to > 'bindings' then it's easier to find & fix this issue later on. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3383: If execution of $q$ completes normally, $e$ evaluates to $i$. On 2016/10/17 16:44:56, eernst wrote: > This is a very special situation, because we cannot say that $q$ completes > normally 'with the value $o$'. This means that the congruence rule in the > comment on line 2383 does not apply directly (because there is no constructor > invocation _expression_). So I'd suggest that we make it explicit here: > > 'If execution of $q$ completes normally then the evaluation of $e$ completes > normally with the value $i$; That's mixing expressions and statements. A statement can "complete normally" and an expression can "evaluate to a value". You can't complete normally with a value. If execution of the constructor as an initializer completes normally (like a statement), then the `new` expression evaluates to $i$. If the constructor throws, so does the expression. Function calls are expressions which contains statements, and for a generative constructor, I actually treat the invocation as a statement, not an expression. > if it completes with an exception then the > evaluation of $e$ completes with the same exception.' Maybe that should be made explicit/ https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3392: % Used to not have the "in-between" clause, which would disallow a factory constructor redirecting to another constructor which conditionally calls the original factory constructor again with different arguments. Not sure what you are asking for. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3399: The result of the evaluation of $e$ is $i$. On 2016/10/17 16:44:55, eernst wrote: > Isn't a factory constructor a function that returns a value? A non-redirecting factory constructor is basically a function. Still, we are invoking it with `new`, not using function call, so we need to duplicate the function-call semantics here as well (I think). > Certainly, > \ref{factories} uses phrases like 'the return type of a factory' and 'a factory > returns'. Yes, it's similar to a function, but it is not a function, and it's not written as "equivalent to the function declaration .... and calling that function". > > Then why not just stick to 'If this execution completes with the returned value > $o$ then the evaluation of $e$ completes normally with the value $o$; if it > completes with an exception, evaluation of $e$ completes with the same > exception'. Because we also have to handle the cases where it completes normally (at least if I remove the implicit "return;" statement added to functions) and where it returns without a value, which both means the same as `return null;`. It doesn't come for free since we are not calling a function, we are executing a body directly. > The reason for including both types of completion is the same as previously: We > hit a generative constructor, so the general propagation rule for expressions > doesn't apply (a similar rule for statements wouldn't apply, either). Actually not. This is a non-redirecting factory constructor, so we won't hit any generative constructor. We are executing a body, which is a block statement, so we have to handle statement completion in general, including completing normally and returning with no value. > > (To 'complete with returned value' is introduced below.) https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3563: If $f$ is marked \ASYNC{} (\ref{functions}), then a fresh instance (\ref{generativeConstructors}) $o$ implementing the built-in class \code{Future} is associated with the invocation and immediately returned to the caller. The body of $f$ is scheduled for execution at some future time. The future $o$ will complete when execution of $f$ completes (\ref{completion}). If $f$ completes by {\em returning} a value, that value used to complete $o$, if it {\em completes normally} or by {\em returning} with no value, $o$ is completed with \NULL{}, and if it completes by {\em throwing} an exception $e$ and stack trace $t$, $o$ is completed with $e$ and stack trace $t$ as an error. On 2016/10/17 16:44:55, eernst wrote: > I'd suggest that we avoid the concept of completing without a value. > Implementations (`dart2js` and `dart`) agree that `void f() { return; }` and > `void g() {}` both return `null` dynamically, and we discussed returning > whatever-you-want in a `void` function, so we are well-situated to simply > declare that there is a return value in all cases. I considered doing that, but Kevin actually liked having the distinction, so I decided to keep it. I don't mind having the distinction between returning with and without a value - it's one more case to handle at the end of a function body, but that's not bad (since it can be lumped with the "completes normally" case). > > So we could do this: > > > '.. If the execution of the body of $f$ completes normally with the value $v$ Mixing expressions and statements. "Complete normally" applies to statements, "with a value" is for expressions. Unless we introduce a new generalizing concept of "completes normally with a value" which combines "returns value", "returns without value" and "completes normally". I'm not sure that's worth it, we only return from functions in so many places. > then the future $o$ completes to $v$; if it completes with an exception then the > future $o$ will complete to the same exception.' > > I searched a bit for the terminology used with future completion, and 'complete > to' seems to exhibit a reasonably clear difference to 'complete with' that we've > used for expressions and now functions. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3568: \item If $f$ {\em completes normally}, then if $s$ has been canceled then its cancellation future is completed with \NULL{} (\ref{null}). Are you sure it's not worth emphasizing that this is a term of art defined elsewhere, and not just prose? I *think* it's easier to read correctly with the emphasis, but since I wrote it, I'm not an objective observer. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3569: \item If $f$ {\em throws} exception $e$ and stack trace $t$: On 2016/10/17 16:44:56, eernst wrote: > Keeping the usual phrases for this, we would have 'If $f$ completes with an > exception throwing the object $o$ and stack trace $t$:' I don't think "completes with an exception" is defined. I have reworded it, so throwing is one of the five ways of completing. It would be either: If $f$ completes by throwing an exception object $o$ and stack trace $t$. or If $f$ throws an exception object $o$ and stack trace $t$. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3572: \item If $s$ has been canceled then its cancellation future is completed with $e$ and $t$ as an error. I think I'll keep using $e$ for the error. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3628: If $f$ completes by {\em throwing}, the invoking call expression throws the same exception object and stack trace. The "last statement" shouldn't need to be mentioned. If the body completes normally, it is because the last statement (if any) has completed normally, but that's not really important. You don't need to worry about which statement is last. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3637: expression can represent the behavior of a function body. ACK. I'm actually considering moving this to the \ref{statements} section - maybe it's possible to define function body execution in a general way, so I won't have to handle the complete-normally/return-with-value/return-without-value -> invocation evaluates to value/null for each type of invocation. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:5044: Next, the stream associated with the innermost enclosing asynchronous for loop (\ref{asynchronousFor-in}), if any, is paused. Execution of the function $m$ immediately enclosing $a$ is suspended until after $f$ completes. At some time after $f$ is completed, control returns to the current invocation. If $f$ has completed with an exception $x$ and stack trace $t$, $a$ {\em throws} $x$ and $t$. If $f$ completes with a value $v$, $a$ evaluates to $v$. It's not, good point. It should be possible to describe this idea behind behavior in more readable terms, without all the details needing to there. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:5456: \LMLabel{statements} But why? I.e., hat are the rules for using LMHash - why must there be an empty line before (and why is LMLabel not introducing a hash automatically)? https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:5457: A {\em statement} is a fragment of Dart code that can be executed at runtime. Statements, unlike expressions, do not evaluate to a value, but are instead executed for their effect on the program state. On 2016/10/17 16:44:57, eernst wrote: > It's a smart phrase, 'Statements, unlike expressions, do not..' but it still > seems twisted. Maybe a small change to 'Unlike expressions, statements do not..' > would make it more smooth to read. Acknowledged. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:5458: Some statements can affect control flow, in particular \BREAK{}, \CONTINUE{}, \RETURN{} and \THROW{} statements. Good point. I'm exactly talking about the things that affect control flow when control comes *out* of the statement/expression. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:5460: \LMLabel{completion} On 2016/10/17 16:44:57, eernst wrote: > It breaks the rules to have an \LMLabel{} which is anywhere else than > immediately after a sectioning command. That's because it produces a label that > refers to the "current number", which is otherwise the number of the section as > shown in the \tableofcontents and used in all the occurrences of > `(\ref{whatever})`. So in this case it would just cause `\ref{completion}` to > work exactly like \ref{statements}. Is it a problem to have two labels for the same section? I know that the \ref will print the same section number, but I like being able to be more precise in the reference. If I ever move this to a subsection, it will still make sense, and I won't have to separate the \ref{statement} into those that refer to one and those that refer to the other. Currently, I think this section is too short to be a sub-section by itself, but I'm not absolutely convinced. If I add more text about function bodies, then I think it should be a subsection. > > So we need to introduce a new section/subsection/.. in order to have something > to refer to. This would make sense anyway, because completion occurs all over > the place. > > That subsection would then refer to the (beginning) of the sections > \ref{statements} and \ref{expressions} etc., wherever we have something about > completion, after giving a brief introduction to the underlying ideas. > > This location would then just have the normal \LMHash{} for each normative > paragraph. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:5461: Execution of a statement can {\em complete} in two ways: either it {\em completes normally} or it {\em aborts}. It can {\em abort} in one of four ways: Either it {\em breaks} or it {\em continues} (either to a label or without a label), it {\em returns}, either with a value or without one, or it {\em throws} an exception object and an associated stack trace. This has been rewritten already. Also, as discussed, making the completion explicit doesn't necessarily require writing "completion". The new text just uses "throws" instead of "completes by throwing", but it's still defined the same way. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:5477: at that point and throws the same exception object and stack trace. Seems reasonable, although doing the S_1 .. S_k seems overkill, and not consistent since it doesn't say anything about multiple expressions, or the interleaving of expressions and statements (for-statements contain multiple expressions - although they might be the only ones). https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:5479: \LMHash{} What is the purpose of LMHash markers? I am thinking of it as a way to split the file into separate sections, roughly by subject, so it's easy to see which sections have changed and which have not. Here I consider the section before the grammar and the grammar to be quite different in subject, so I want them seprated. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:5525: On 2016/10/17 16:44:57, eernst wrote: > Just for consistency, let's keep 2 empty lines before sections. Acknowledged. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:5751: then the statement is treated as if it had completed normally. If the body continues the loop, then it's equivalent to the body completing normally. It's incorrect to goto beginIteration here, you need to go to the evaluation of the increment-part (the third part of the for-statement) below. (A continue of a loop is always equivalent to breaking the body statement, so it's equivalent to the body completing normally). https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:5753: execution of the for loop stops and aborts in the same way. That, or remove it. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... File docs/language/dartLangSpec.tex (right): https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5816: This allows other asynchronous events to execute while this loop is waiting for stream events. I'm not sure where we define "suspend", so I thought it important to say what it means to suspend the execution. I'll make this a rationale.
All (I hope) comments addressed, PTAL https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.tex File docs/language/dartLangSpec.tex (right): https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1215: A {\em generative constructor} is executed to initialize a freshly allocated object. On 2016/10/19 14:34:32, Lasse Reichstein Nielsen wrote: > I want to say something here because it introduces a new mode of execution > (execution to initialize a new object). This is similar to the text written > about statements and expressions describing that they can be executed and > evaluated respectively. A generative constructor can be "executed to > initialize". > > That said, it's not saying much, so let's just drop it. > > > As discussed, the allocation happens below. that's fine with me - the `new` > operator allocates the object, the constructors initialize the new object. Done. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1353: and the type parameters of the immediately enclosing class bound to a set of actual type arguments $V_1, \ldots , V_m$. On 2016/10/19 14:34:31, Lasse Reichstein Nielsen wrote: > The constructor $k$ is invoked on a type $T$. The $T$ may be a parameterized > class type with type parameters. > > I guess I should add "of the type $T$" above after "generative constructor $k$". Done. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1358: On 2016/10/17 16:44:57, eernst wrote: > No need for two empty lines: No new sections here. Done. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1377: %Next, a On 2016/10/19 14:34:31, Lasse Reichstein Nielsen wrote: > We could delete all the comments. > A few might me relevant, but they are still in the git history. Done. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1408: Execution of an initializer of the form \code{\THIS{}.$v$ = $e$} to initialize an object $i$ proceeds as follows: On 2016/10/19 14:34:31, Lasse Reichstein Nielsen wrote: > ACK Done. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1427: This evaluated argument list is remembered until after the entire initializer list has been evaluated, at which point the constructor is executed as follows: Actually, I don't think the binding of formal variables includes the handling of initializing formals anyway. That's handled explicitly by this section based on the existing binding of formal variables. So, let's just say that we create a binding here and use it later. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:1433: The generative constructor $S$ (respectively $S.id$) of $S$ is executed to initialize $i$ with respect to the bindings that resulted from the evaluation of the argument list, and the type parameters (if any) of class $S$ bound to the current bindings of $U_1, , \ldots, U_m$. It's still suspicious that we talk about the "Actual type arguments" ( a dynamic property) of the superclass clause (a syntactic entity). I'm not going to fix that in this CL, but it's probably worth looking into. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:2383: at that point and throws the same exception. We won't use "complete" for expressions. I have tried making the emphasis more consistent. I also don't want to talk about evaluating multiple expressions in any order. That's exactly the kind of non-compositionality that causes problems (it fails to recognize that evaluation might do other things between evaluating expressions that can also throw). It might not be the case currently, but I would prefer to not depend on that. I have removed the "unless otherwise stated" for now, that's easy to add if it becomes necessary. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:2384: On 2016/10/17 16:44:57, eernst wrote: > Typo: Spurious empty line. Done. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3097: There is no requirement that the expression $e$ evaluate to a special kind of exception or error object. I actually find that more confusing than not having it. It's restating the general rule. I removed "exception or error", there is no requirement that it evaluates to any special kind of object (full stop). https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3101: If $e$ evaluates to \NULL{} (\ref{null}), then a \code{NullThrownError} is thrown. Otherwise let $t$ be a stack trace corresponding to the current execution state, and the \THROW{} statement aborts by {\em throwing} with $e$ as exception object and $t$ as stack trace. Added newlines, removed emphasis. Changed ref to {evaluation} since this is an expression, not a statement. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3381: Then $q$ is executed to initialize $i$ with its formal parameters bound to the evaluated argument list and, if $R$ is a generic class, with its type parameters bound to $V_1 \ldots V_m$. I'm wrong. Reworded to be consistent with other similar sections: "with respect to the bindings that resulted from the evaluation of ...." https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3383: If execution of $q$ completes normally, $e$ evaluates to $i$. No explicitly propagates exception from execution to evaluation, since \ref{evaluation} doesn't handle that implicitly - it only handles sub-expressions, not sub-executions (generative constructor invocation is actually neither, but I treat it as a function invocation, and function invocations are underspecified too) https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3396: Otherwise, the body of $q$ is executed with respect to the bindings that resulted from the evaluation of the argument list and the type parameters (if any) of $q$ bound to the actual type arguments $V_1, \ldots, V_l$. On 2016/10/17 16:44:57, eernst wrote: > We definitely need to have a comma here: '..argument list, and..'. > > Actually: '..argument list, and with the type parameters..' would work better, > because then we have 'with respect to .. bindings' and 'with type parameters .. > bound'. Done. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3568: \item If $f$ {\em completes normally}, then if $s$ has been canceled then its cancellation future is completed with \NULL{} (\ref{null}). On 2016/10/19 14:34:31, Lasse Reichstein Nielsen wrote: > Are you sure it's not worth emphasizing that this is a term of art defined > elsewhere, and not just prose? > I *think* it's easier to read correctly with the emphasis, but since I wrote it, > I'm not an objective observer. Done. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3602: \item If $f$ {\em completes normally}, $j$ is positioned after its last element, so that its current value is \NULL{} and the current call to \code{moveNext()} on $j$ returns false, as will all further calls. Not using that phrasing. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3603: \item If $f$ {\em throws} exception $e$ and stack trace $t$ then the current value is \NULL{} and the current call to \code{moveNext()} throws $e$ and $t$ as well. Further calls must return false. On 2016/10/17 16:44:55, eernst wrote: > 'If $f$ completes with an exception then a call to \code{moveNext()} must > complete with the same exception, and the current value must be \NULL{}. Further > calls to \code{moveNext()} must return false.' > > I guesstimated that the further calls would be to `moveNext()`, but since that > wasn't immediately obvious I think we should make it explicit. Done. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:3637: expression can represent the behavior of a function body. REmoved \em's. Reworded. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:5041: If $e$ evaluates to an object $o$ that is not an instance of \code{Future}, then let $f$ be the result of creating a new object using the constructor \code{Future.value()} with $o$ as its argument; otherwise let $f$ be the result of evaluating $e$. I have trouble parsing that. I read it as: if (e evaluates to a value o that is not Future) { let f = new Future.value(o) } else { let f = o } but o is not in scope in the else branch. Kept (almost) as written. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:5457: A {\em statement} is a fragment of Dart code that can be executed at runtime. Statements, unlike expressions, do not evaluate to a value, but are instead executed for their effect on the program state. The more I think about it, the less I agree. We are talking about statements, so starting the sentence with "expressions" is less direct. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:5458: Some statements can affect control flow, in particular \BREAK{}, \CONTINUE{}, \RETURN{} and \THROW{} statements. I have reworded considerably, this sentence is now gone. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:5477: at that point and throws the same exception object and stack trace. Kept the existing text mostly unchanged. Getting into talking about multiple statements or expressions at the same time leads to having to consider interleaving and ordering, which is strictly worse than just talking about one at a time. I don't like the lead-in "we need to" (To channel Yoda: Do or do not, there is no "need to"). Moved examples to end of paragraphs. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:5751: then the statement is treated as if it had completed normally. Reworded. https://codereview.chromium.org/2399343002/diff/1/docs/language/dartLangSpec.... docs/language/dartLangSpec.tex:5753: execution of the for loop stops and aborts in the same way. Removed. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... File docs/language/dartLangSpec.tex (right): https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5805: Execution of a for-in statement, $f$, of the form \code{\AWAIT{} \FOR{} (finalConstVarOrType? id \IN{} $e$) $s$} proceeds as follows: On 2016/10/19 13:37:04, eernst wrote: > We do have a couple of occurrences of `id` as a meta-variable occurring in a > `\code{..}` context (rather than math mode as in `$id$`). > > However, these cases are clearly the exception (and some of them seem to be > motivated by being in a non-normative context, where the use of math mode > clashes with plain italic to make everything look like regular text). In this > context we already have $e$ and $s$, and there are lots of similar elements > saying "syntactic meta-symbols use math mode". > > It is a bit messy to use multi-letter symbols in math mode, but `id` isn't that > bad (something like $buffer$ is much worse because of the big difference between > $f$ and \itshape{f}), and we also have $type$, $inherited$, $overrides$, and > more. > > So I'd suggest that we use $id$. Done. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5813: The stream $o$ is listened to, producing a stream subscription $u$, On 2016/10/19 13:37:04, eernst wrote: > Yes, thank you! The spec mentions stream subscriptions a few times, but they > haven't been introduced anywhere. Acknowledged. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5823: If the subscription is already paused, the \code{pause} call may be omitted. On 2016/10/19 13:37:05, eernst wrote: > I think it gets too difficult to distinguish commentary and normative text if > they occur together (the font difference doesn't scream it out). > > I did find exceptions (and I was surprised to find them), but it is very nearly > consistently enforced that commentary is put into its own paragraph. > > I'd prefer if we maintain that style. Done. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5827: the statement $s$ is executed with \code{id} bound to the value of the current data event. On 2016/10/19 13:37:05, eernst wrote: > \code{id} --> $id$ Done. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5830: If another event $e_u$ of $u$ occurs before execution of $s$ is complete, handling of $e_u$ must wait until $s$ is complete. We can pause the source stream. That will definitely ensure that we do wait until $s$ is complete. On the other hand, it also enforces pausing even when it isn't necessary, which is what this text tries to avoid. However, the way the spec is currently written, we can just say nothing, and then any async operation inside $s$ *will* pause the stream. Then it's just a corollary that the next event will be delayed, and this can be a commentary. Except for badly implemented streams that fire during synchronous execution. Or that ignore pause and cancel calls. We can't save the world from that, so the question is how precisely we must specify the semantics - must all programs have a completely specified semantics, so you can derive what happens even for a completely broken stream, or do we leave it implementation dependent what happens if you don't follow the stream semantics. The former is doable, but will require quite complicated implementations that duplicate a lot of the logic of correct streams. The latter is probably all you need in practice. I'm going for the latter. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5833: If execution of $s$ {\em continues} with no label, or with a label that prefixes the asynchronous for statement (\ref{labels}), then the execution of $s$ is treated as if it had completed normally. Removing all the {\em's}. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5845: until $u$ is no longer paused. Let's do that. https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5917: Then, the expression $e$ is evaluated to an object $o$. Then, $o$ is subjected to boolean conversion (\ref{booleanConversion}), producing an object $r$. If $r$ is \FALSE{}, execution of the do statement completes normally. Do we need this reference when we had one in the previous paragraph? https://codereview.chromium.org/2399343002/diff/40001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6039: If $v$ is not \TRUE{} the following case, \CASE{} $e_{k+1}: s_{k+1}$ is matched against {\code id} if it exists. If \CASE{} $e_{k+1}: s_{k+1}$ does not exist, then the \DEFAULT{} clause's statements are executed (\ref{case-execute}). Rewritten again to not say "if such a thing exists" but just "if k < n" - which amounts to the same thing. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... File docs/language/dartLangSpec.tex (right): https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5777: or {\em continues} with a label that prefixes this \FOR{} statement (\ref{labels}), On 2016/10/19 13:37:05, eernst wrote: > Following the newest plan (around noon, Oct 19), this would not have the {\em..} > around completion related words, but it would have (\ref{completion}) after the > completion related phrase. We could put it 3 times, but maybe this will suffice > (because we have `continues` so close to `with.. a label` everywhere): > > `If this execution completes normally, continues without a label, or continues > with a label (\label{labels}) that prefixes this \FOR{} statement > (\ref{completion})` Done. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5879: On the first {\em error event} from $u$, Error events are a defined term for streams. They arise by the source putting an error event into the stream, they are detected by the stream subscription calling the onError handler. This is no more (or less) controversial, or less defined, than using "data event" above. The current specification was written in imprecise terms. The precise terms would be that you pass callback functions in the listen call (which is then also made explicit) and you act when those callback functions are called. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5913: Why? Do we need \LMHash between all paragraphs? https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:5915: If that execution {\em completes normally} or it {\em continues} with no label or with a label that prefixes the \WHILE{} statement (\ref{labels}), then the while statement is re-executed. Done. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6040: The statement \code{\VAR{} id = $e$;} is evaluated, where \code{id} is a variable whose name is distinct from any other variable in the program. In checked mode, it is a run time error if the value of $e$ is not an instance of the same class as the constants $e_1 \ldots e_n$. On 2016/10/19 13:37:05, eernst wrote: > `id` --> `$id$` in the statement, `\code{id}` --> `$id$` otherwise. > > We already have many occurrences of `fresh variable` in the spec, so we could > reduce `a variable whose name is distinct from any other variable in the > program` to that. Done. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6045: Next, the case clause \CASE{} $e_{1}: s_{1}$ is matched against {\code id} if such a case clause exists. If \CASE{} $e_{1}: s_{1}$ does not exist, then if there is a \DEFAULT{} clause, its statements, if any, are executed (\ref{case-execute}). On 2016/10/19 13:37:07, eernst wrote: > We did introduce $s_{n+1}$ a few lines earlier, so the issue is not whether > \DEFAULT{} has any statements, it's whether there is a \DEFAULT{} clause at all. > I'd prefer this: > > `.. if there is a \DEFAULT{} clause, its statements $s_{n+1}$ are executed`. Done. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6048: Matching of a \CASE{} clause \CASE{} $e_{k}: s_{k}$ of a switch statement Because I now add braces around the statements before executing them. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6059: against a value {\code id} proceeds as follows: On 2016/10/19 13:37:07, eernst wrote: > `{\code id}` --> `$id$`. > > I actually think the following text reads better if we use the opposite > ordering: Put 'Matching of a value $id$ against a \CASE{} clause \CASE{} $e_k: > s_k$ of a switch statement' before the code environment, and then just 'proceeds > as follows:' here. Done. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6062: The expression \code{$e_k$ == id} is evaluated to an object $o$ which is then subjected to boolean conversion producing a value $v$. I prefer not to use "yield" since that means something specific in Dart. Boolean conversion is a function invocation, but it's probably better seen as an expression evaluation. I think I'll rewrite 'boolean conversion producing" into "boolean conversion evaluating to" https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6063: If $v$ is not \TRUE{} the following case, \CASE{} $e_{k+1}: s_{k+1}$ is matched against {\code id} if such a case clause exists. If \CASE{} $e_{k+1}: s_{k+1}$ does not exist, then the \DEFAULT{} clause's statements are executed (\ref{case-execute}). \ref{case-execute} is about executing the *statements* of a case or default clause. It's not case-matching. It is needed because execution of case statements need to know about the surrounding switch case so it can properly jump on a continue-to-label. I think the simplest way to specify this is to handle the continue at the end of the execution of the case-statements. The alternative is to let the continue bubble up and complete the switch case, and then add an extra clause saying that if the switch case continues to a label declared by the switch case, the switch statement is re-executed from the execution of the related statements. This leaving and reentering the switch statement is too confusing, so I'm making this iterative on the case statement block execution. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6080: The expression \code{$e_k$ == id} is evaluated to an object $o$ which is then subjected to boolean conversion producing a value $v$. evalautes to https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6081: If $v$ is not \code{true} the following case, \CASE{} $e_{k+1}: s_{k+1}$ is matched against {\code id} if it exists. I see varying uses of true and \TRUE{}, but \code{true} is right out. I think I'll use \TRUE{} here for temporary consistency, and then we can look at it later and see if "true" or "\TRUE{}" is better https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6082: If $v$ is \code{true}, let $h$ be the smallest integer such that $h \ge k$ and $s_h$ is non-empty. If no such $h$ exists, let $h$ be $n$. The sequence of statements $s_h$ is executed (\ref{case-execute}). \TRUE{}, keeping the ref with a slight rewording. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6117: \subsubsection{ Switch case statements} Thanks. :) https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6119: Execution of the statements $s_h$ of a switch statement On 2016/10/19 13:37:05, eernst wrote: > Please add empty line and `\LMHash{}` in front of normative paragraph. Done. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6159: execution of the switch statement continues with the case labeled by that label. Removed entire line, it's purely explanatory, the following lines says exactly what happens. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6164: This extra text and index manipulation is only necessary due to 'continue label". It's not really affected by the implicit throw. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6224: A set of \ON{}-\CATCH{} clauses, each of which specifies (either explicitly or implicitly) the type of exception object to be handled, two exception parameters and a block statement. Yes, and the grammar above does. There is "catch without stack variable equivalent to one with" section below. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6237: An \ON{}-\CATCH{} clause of the form \code{\ON{} $T$ \CATCH{} ($p_1$) $s$} is equivalent to an \ON{}-\CATCH{} clause \code{\ON{} $T$ \CATCH{} ($p_1, p_2$) $s$} where $p_2$ is an identifier that does not occur anywhere else in the program. Agree https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6237: An \ON{}-\CATCH{} clause of the form \code{\ON{} $T$ \CATCH{} ($p_1$) $s$} is equivalent to an \ON{}-\CATCH{} clause \code{\ON{} $T$ \CATCH{} ($p_1, p_2$) $s$} where $p_2$ is an identifier that does not occur anywhere else in the program. On 2016/10/19 13:37:07, eernst wrote: > We have 12 occurrences of `fresh variable` and only two (until now) of > identifier-or-variable that `does not occur`, so we might as well use `fresh > variable` everywhere in new material. Agree > We should then make sure that it is defined once and for all, possibly in > \section{Overview}. I don't think it fits in Overview, so I put it in Notation. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6240: An \ON{}-\CATCH{} clause of the form \code{\ON{} $T$ $s$} is equivalent to an \ON{}-\CATCH{} clause \code{\ON{} $T$ \CATCH{} ($p_1, p_2$) $s$} where $p_1$ and $p_2$ are identifiers that do not occur anywhere else in the program. On 2016/10/19 13:37:06, eernst wrote: > `fresh variable` Done. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6243: An \ON{}-\CATCH{} clause of the form \code{\CATCH{} ($p$) $s$} is equivalent to an \ON{}-\CATCH{} clause \code{\ON{} \DYNAMIC{} \CATCH{} ($p$, $p_2$) $s$} where $p_2$ is an identifier that does not occur anywhere else in the program. On 2016/10/19 13:37:06, eernst wrote: > `fresh variable` Done. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6264: If execution of $b$ {\em throws} (\ref{completion}) with exception object $e$ and stack trace $t$, then $e$ and $t$ are matched against the \ON{}-\CATCH{} clauses to yield a new completion (\ref{on-catch}). On 2016/10/19 13:37:07, eernst wrote: > Just 'throws'. Done. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6270: Otherwise if execution of $b$ threw, the \TRY{} statement completes in the same way as the matching against the \ON{}-\CATCH{} clauses. On 2016/10/19 13:37:05, eernst wrote: > `threw (\ref{completion})` Done. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6273: \subsubsection{\ON{}-\CATCH{} clauses} Why add a label if it isn't referenced? https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6283: If there are no \ON{}-\CATCH{} clauses ($n = 0$), matching completes by {\em throwing} the exception object $e$ and stack trace $t$. Throws. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6286: \LMHash{} On 2016/10/19 13:37:05, eernst wrote: > Move `LMHash` up in front of the paragraph, and add one just before the next > one. Done. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6290: It is of course a static warning if $T_i$, $1 \le i \le n$ is a deferred or malformed type. On 2016/10/19 13:37:06, eernst wrote: > Delete 'of course' and move this sentence up a few lines to a context where the > `try` statement is discussed as a whole. Done. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6304: Yes - that cancelling of the subscription of an await-for is now specified with the await for, independently of how the body completes. Not sure what about stack traces you are referring to. The spec now does say something about stack traces - they are introduced at throws and propagated with the exception. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6324: Then the return statement completes by \em{returning} the value $o$ (\ref{completion}). Just: returns the value $o$ https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6332: \LMHash{} Good point. Must have gotten lost somewhere. I think I'll just reintroduce it here, and then if it needs to be moved, we can do it later. I think it's a good thing if the stack trace corresponds to the return statement, so it probably should be thrown here. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6361: Executing a return statement with no expression, \code{\RETURN;} {\em returns} with no value (\ref{completion}). This is well-defined. If a function invocation's execution of the function body returns without a value, the function invocation expression evaluates to null. There is no change to the semantics, and the static type shouldn't be affected by anything. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6390: The namespace of labels is distinct from the one used for types, functions and variables. It's not new - it's just separated from its original paragraph. But done. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6415: Execution of a \BREAK{} statement \code{\BREAK{} label;} completes by {\em breaking} with the label \code{label} (\ref{completion}). On 2016/10/19 13:37:07, eernst wrote: > `{\em breaking}` --> `breaking`. > > We have the same issue here is before with `id`: It ought to be $label$, unless > that is too unreadable. If it looks bad then we can use `\mbox{\em label}`, > which will work in a math context and produce reasonable kerning. Done. Changed the label to $L$. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6417: Execution of a \BREAK{} statement \code{\BREAK{};} completes by {\em breaking} without a label (\ref{completion}). On 2016/10/19 13:37:06, eernst wrote: > `{\em breaking}` --> `breaking`. Done. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6435: Execution of a \CONTINUE{} statement \code{\CONTINUE{} label;} completes by {\em continuing} with the label \code{label} (\ref{completion}). On 2016/10/19 13:37:06, eernst wrote: > `continuing` Done. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6437: Execution of a \CONTINUE{} statement \code{\CONTINUE{};} completes by {\em continuing} without a label (\ref{completion}). On 2016/10/19 13:37:06, eernst wrote: > `continuing` Done. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6465: If the enclosing function $m$ is marked \ASYNC* and the stream $u$ associated with $m$ has been canceled, then the \YIELD{} statement completes by {\em returning} \code{null} (\ref{completion}), otherwise it completes normally. On 2016/10/19 13:37:07, eernst wrote: > `returning` Done. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6525: \item The getter \cd{current} is invoked on $i$. If the invocation {\em throws} an exception $ex$, execution of $s$ completes in the same way. Otherwise, the result $x$ of the getter invocation is added to the iterable associated with $m$. Reworded since the invocation is an expression, so it's \ref{evaluation}. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6543: Then, if the cancel completed normally, the stream execution of $s$ {\em returns} with no value (\ref{completion}). On 2016/10/19 13:37:06, eernst wrote: > `returns` Done. https://codereview.chromium.org/2399343002/diff/60001/docs/language/dartLangS... docs/language/dartLangSpec.tex:6575: It is a dynamic type error if $o$ is not of type \code{bool} or of type \code{Function}, or if $r$ is not of type \code{bool}. If $r$ is \FALSE{}, we say that the assertion failed. If $r$ is \TRUE{}, we say that the assertion succeeded. If the assertion succeeded, execution of the assert statement is complete. If the assertion failed, the execution {\em throws} an \code{AssertionError} with a stack trace corresponding to the \ASSERT{} statement. On 2016/10/19 13:37:07, eernst wrote: > `the execution throws .. to the current execution state at the \ASSERT{} > statement (\ref{completion}).` Done.
Reached line 6430, will recover now, and finish the review tomorrow. ;-) https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... File docs/language/dartLangSpec.tex (right): https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:1218: A {\em constructor} is a special function that is used in instance creation expressions (\ref{instanceCreation}) to create or initialize objects. A factory constructor would not necessarily create any objects, nor necessarily initialize any objects, it could simply return an already existing object. So it's not a logical 'or' in 'create or initialize', it is more like 'create and initialize' for generative constructors, and not necessarily any of them for factories. How about just admitting that this is a first approximation, and say '..to obtain objects, typically by creating and initializing them.'? https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:1377: We should remove the empty line (to ensure `\LMHash{}` includes the paragraph below, and we might as well delete the "..allocated" sentence above, because allocation is accounted for elsewhere, and it's simply wrong to have it here. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:1383: Any initializing formals declared in $k$'s parameter list are executed in the order they appear in the program text. So we will evaluate `e` in `T x = e;` when we also have `C(this.x)` (getting the side-effects from`e`, storing the value, then overwriting it). Didn't we agree at some point that the initializing formal should preempt the evaluation of the in-decl initializing expression? I can see below that a `final` field cannot have a second initialization in a constructor initializer list because it is a runtime error to make the attempt, so we are consistently evaluating all the initializers, and getting all the side-effects, or failing in the attempt to do so. But this combination of double side-effects for non-finals and an error for finals is not pretty. We could as well have prioritized the initializing expressions and avoided both the double side-effects and the error. That seems more useful and equally consistent. It may be confusing in its own way: you can't stare at an initializer and trust it to be executed -- but in the other model you can't stare at an initializer and trust that the variable will have that value. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:1391: Then if any instance variable of $i$ declared by the immediately enclosing class Prepend `\LMHash{}` https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:1396: Then, unless the enclosing class is \code{Object}, the explicitly specified or Prepend `\LMHash{}` https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:1422: First, the expression $e$ is evaluated to an object $o$. Then, the instance variable $v$ of $i$ is bound to $o$, unless $v$ is a final variable that has already been initialized, in which case a runtime error occurs. In checked mode, it is a dynamic type error if $o$ is not \NULL{} and the interface of the class of $o$ is not a subtype of the actual type of the field $v$. `unless .. already initialized`: Currently we get a warning in dartpad for `class C { final x = 1; C(): x = 2; }`, and 'Run' produces 'Error compiling to JavaScript: [error on line 3] Field 'x' is initialized more than once.'. Somewhat uncharted waters here. ;-) In Dart 1 it makes sense to give a warning at compile time and fail at run time, and it would also be OK (though more Dart 2.0-ish) to make it a compile-time error. Apparently the analyzer emits a warning, and dart2js makes it a compile-time error. Given that `C()` is now a compile-time error when `C` denotes a class, we could make this double-init situation a compile time error for final variables (because all names are bound statically, and it won't work at runtime, just like `C()`). After all, it is a compile-time error to have a double-initialization via an initializing formal plus an entry in the initializer list of the same constructor. We probably can't get rid of the double-initialization approach for non-final variables, because there may be software out there relying on having all the side-effects. Maybe in 2.0.. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:1439: Then, after the remainder of the initializer list of $k$ has been executed, Prepend `\LMHash{}` https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:2389: \LMLabel{evaluation} We shouldn't have an `\LMLabel{evaluation}`, because \ref{evaluation} is the same thing as \ref{expressions}. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:2395: Every expression has an associated static type (\ref{staticTypes}). Prepend `\LMHash{}` https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:2398: If evaluation of an expression, $e$ is defined in terms of evaluation of another expression, Prepend `\LMHash{}`. I'd prefer 'an expression $e$' or 'an expression, $e$,'. The single comma before $e$ is confusing. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:2613: The \code{Null} class declares no methods except those also declared by \code{Object}. Do we need to know that Null overrides all the inherited methods from Object? Is it true? Maybe we could use '.. class has no methods except..'? https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:2653: it denotes the hexadecimal integer numeral It is my understanding (and Googling 'numeral meaning' confirms ;-) that a 'numeral' is a syntactic entity. This means that nothing denotes a numeral, but the numeral may denote a number (say, an integer), which is a semantic entity that may have many different designations/notations. I know you have a point to make here, but I'd like to hear some arguments for a different interpretation because right now it just looks wrong to add 'numeral' in that location. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:2656: it denotes a decimal integer numeral. Same issue with the added 'numeral'. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:2658: with the integer value represented by that numeral. I can see that the model is "syntax --denotes--> numeral --represents--> integer value", but I can't see why it would make sense to have the middle layer, nor what kind of entities the middle layer would contain. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:2697: It is a compile-time error for a class to attempt to extend, mix in or implement\code{ bool}. We don't have a precise definition of 'attempt to extend' etc. so let's just make it 'error for a class to extend..'. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:2901: All string literals evaluates to instances of the built-in class \code{String}. It is a compile-time error for a class to attempt to extend, mix in or implement \code{String}. `evaluates` --> `evaluate`, and change to `error for a class to extend..` https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:3000: First, the expressions $e_1 \ldots e_n$ are evaluated in order they appear in the program, producing objects $o_1 \ldots o_n$. What's wrong with 'yielding'? ('yielding' --> 'producing' occurs several times at least, but I won't comment on them all). https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:3425: Otherwise execution of $q$ throws an exception object $x$ and stack trace $t$ , Remove space before comma. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:3640: \item If it throws en exception object $e$ and stack trace $t$ then the current value of $j$ is \NULL and the current call to \code{moveNext()} throws $e$ and $t$ as well. Further calls to \code{moveNext()} must return false. Typo: `en` --> `an`. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:5477: \LMLabel{completion} To allow `\LMLabel{completion}` to have a meaningful effect it should be located immediately after a sectioning command. As it is here, it is just a new name for the label `statements`. So we ought to create a completion section, or just use the `statements` label to refer to completion. Maybe we should simply create a new top level section (a `\section{Completion}`) and put it just before the Statements section? https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:5485: and the execution of that other statement doesn't complete normally, `doesn't` --> `does not` https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:5497: For example, if evaluation the condition expression of an \IF{} statement throws, `evaluation [of] the condition` https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:5837: This allows other asynchronous events to execute while this loop is waiting for stream events. This sentence is commentary. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:5841: If the subscription is already paused, the \code{pause} call may be omitted. I don't understand this: Presumably it's not the developer who could omit a syntactic invocation of `pause`, so maybe it means `If the subscription is already paused, an implementation may omit the invocation of \code{pause}`? https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:5858: loop is unspecified. (1) The spec does not otherwise leave semantics unspecified; (2) this sentence is normative, so it should not be in a `\commentary{}`. Can we avoid it? https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:5913: If $r$ is \FALSE{}, then execution of the while statement completes normally Prepend `\LMHash{}` https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:5916: Otherwise $r$ is \TRUE{} and then the statement $\{s\}$ is executed. Prepend `\LMHash{}` https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:5918: If the execution breaks without a label, execution of the while statement completes normally. Why couldn't it 'break with a label that prefixes the \WHILE{} statement'? (Returning to this comment, it is resolved in line 6404. But it would be nice to have a small commentary here explaining it.) https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:6061: against a the value of a variable $id$ proceeds as follows: Typo: spurious `a`. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:6167: let $h$ be the smallest number such that $h \ge i$ and $s_h$ is non-empty. If no such $h$ exists, and let $h = n + 1$ if the \SWITCH{} statement has a \DEFAULT{}, otherwise let $h = n$. This doesn't parse. Is it just a spurious `and` in the middle? https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:6231: A set of \ON{}-\CATCH{} clauses, each of which specifies (either explicitly or implicitly) the type of exception object to be handled, two exception parameters and a block statement. I think we need to keep `one or two` exception parameters here, because this is about the syntax that programmers can use. We will use the equivalence below to explain why it is enough to _specify_ the form that has two exception parameters. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:6276: Otherwise if execution of $b$ threw (\ref{completion}), the \TRY{} statement completes in the same way as the matching against the \ON{}-\CATCH{} clauses . Spurious space before period. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:6282: It is a static warning if $T_i$, $1 \le i \le n$ is a deferred or malformed type. Why is this commentary? Aren't static warnings otherwise normative? https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:6404: then execution of $s$ completes normally, Ah! Now I can see why there was no need to have `breaks with a label that prefixes <blah>`.
Just one typo this time. LGTM!! https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... File docs/language/dartLangSpec.tex (right): https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:6563: Otherwise, $x$, or $e$ with $t$, are added to the stream associated with $m$ in the order they appears in $o$. The function $m$ may suspend. Typo: `appears` --> `appear`
https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... File docs/language/dartLangSpec.tex (right): https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:1218: A {\em constructor} is a special function that is used in instance creation expressions (\ref{instanceCreation}) to create or initialize objects. On 2016/11/23 16:26:42, eernst wrote: > A factory constructor would not necessarily create any objects, nor necessarily > initialize any objects, it could simply return an already existing object. So > it's not a logical 'or' in 'create or initialize', it is more like 'create and > initialize' for generative constructors, and not necessarily any of them for > factories. How about just admitting that this is a first approximation, and say > '..to obtain objects, typically by creating and initializing them.'? Done. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:1377: On 2016/11/23 16:26:40, eernst wrote: > We should remove the empty line (to ensure `\LMHash{}` includes the paragraph > below, and we might as well delete the "..allocated" sentence above, because > allocation is accounted for elsewhere, and it's simply wrong to have it here. Done. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:1383: Any initializing formals declared in $k$'s parameter list are executed in the order they appear in the program text. I'm not sure we agreed to changing it (at least I don't remember it), so I went for specifying the way it's currently working. If we decide to change it, we can take it from there. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:1383: Any initializing formals declared in $k$'s parameter list are executed in the order they appear in the program text. Added LMHash here too. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:1391: Then if any instance variable of $i$ declared by the immediately enclosing class On 2016/11/23 16:26:40, eernst wrote: > Prepend `\LMHash{}` Done. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:1396: Then, unless the enclosing class is \code{Object}, the explicitly specified or On 2016/11/23 16:26:42, eernst wrote: > Prepend `\LMHash{}` Done. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:1422: First, the expression $e$ is evaluated to an object $o$. Then, the instance variable $v$ of $i$ is bound to $o$, unless $v$ is a final variable that has already been initialized, in which case a runtime error occurs. In checked mode, it is a dynamic type error if $o$ is not \NULL{} and the interface of the class of $o$ is not a subtype of the actual type of the field $v$. I think compile-time warning/runtime error is good enough for this for Dart 1. Dart 2 will be compile-time error instead (we don't specify semantics for programs with compile-time detectable errors). So, yes. I didn't actually make C() a compile time error yet. I just specified the current behavior which is a static warning/runtime error (calling C like a function when it's actually a type literal evaluating to a Type object that isn't callable). https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:1439: Then, after the remainder of the initializer list of $k$ has been executed, On 2016/11/23 16:26:42, eernst wrote: > Prepend `\LMHash{}` Done. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:2389: \LMLabel{evaluation} Is that a problem? Should I use \label{evaluation} instead? https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:2395: Every expression has an associated static type (\ref{staticTypes}). On 2016/11/23 16:26:42, eernst wrote: > Prepend `\LMHash{}` Done. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:2398: If evaluation of an expression, $e$ is defined in terms of evaluation of another expression, Done, plus small rewrite. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:2613: The \code{Null} class declares no methods except those also declared by \code{Object}. That depends on what "declares" means. The interface of Null has those members, and no other. The class of Null overrides some, but not all, of them. It's an implementation details which ones (in practice it might just be toString). I think this text is fine - it allows Null to override all the methods, and it's a valid optimization to not do it anyway. People with mirrors might be able to tell, if they can find the declaring class of a member of Null, but I don't particularly care at that point. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:2653: it denotes the hexadecimal integer numeral As discussed offline, the point was that "hexadecimal number" is meaningless, so I changed it to "hexadecimal numeral". I've changed the sentence so "denotes" now refers to a semantic entity and "numeral" to the syntax. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:2656: it denotes a decimal integer numeral. On 2016/11/23 16:26:42, eernst wrote: > Same issue with the added 'numeral'. Done. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:2658: with the integer value represented by that numeral. Changed to "numeric literal" is/contains "decimal/hexadecimal numeral" denotes "integer"/"number". In that way, a "numeric literal" is a syntax production and "decimal/hexadecimal numeral" is a strategy to interpret the syntax which gives an "integer" value (member of ℕ actually, since the leading minus is an operator, not part of the literal). https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:2697: It is a compile-time error for a class to attempt to extend, mix in or implement\code{ bool}. Done. Also fixed for int/double/num aand String. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:2901: All string literals evaluates to instances of the built-in class \code{String}. It is a compile-time error for a class to attempt to extend, mix in or implement \code{String}. On 2016/11/23 16:26:42, eernst wrote: > `evaluates` --> `evaluate`, and change to `error for a class to extend..` Done. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:3000: First, the expressions $e_1 \ldots e_n$ are evaluated in order they appear in the program, producing objects $o_1 \ldots o_n$. Just a suggestion to not use "yield" here since "yield" is now a keyword in the language with a different meaning. That is, just to avoid potential confusion and leave the "yield" word open for use in describing the action of the "yield" statement. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:3425: Otherwise execution of $q$ throws an exception object $x$ and stack trace $t$ , On 2016/11/23 16:26:41, eernst wrote: > Remove space before comma. Done. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:3640: \item If it throws en exception object $e$ and stack trace $t$ then the current value of $j$ is \NULL and the current call to \code{moveNext()} throws $e$ and $t$ as well. Further calls to \code{moveNext()} must return false. On 2016/11/23 16:26:42, eernst wrote: > Typo: `en` --> `an`. Done. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:5477: \LMLabel{completion} I don't want to put completion of statements before defining statements. I do want to describe it before the grammar. I also want my references to be precise, in case we find a way to restructure it anyway, so I want a label that refers to the completion. Should I change it to just "\label"? https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:5485: and the execution of that other statement doesn't complete normally, On 2016/11/23 16:26:41, eernst wrote: > `doesn't` --> `does not` Done. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:5497: For example, if evaluation the condition expression of an \IF{} statement throws, On 2016/11/23 16:26:41, eernst wrote: > `evaluation [of] the condition` Done. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:5837: This allows other asynchronous events to execute while this loop is waiting for stream events. On 2016/11/23 16:26:41, eernst wrote: > This sentence is commentary. Done. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:5841: If the subscription is already paused, the \code{pause} call may be omitted. True. Done. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:5858: loop is unspecified. (1) Sure it does. For example, it doesn't say how "await" waits for a future to complete. It must be done by adding a `then` listener and either an onError callback on the then or a catchError call to get the error. It's completely unspecified what happens if a badly implemented future calls both callbacks or calls one of the callbacks twice. The problem is generally with the specification handing out callbacks and making *any* assumption about how they are invoked. It's hard to avoid that problem completely without overspecifying the semantics and adding significant overhead to implementations, and for no practical reason in all but completely borked programs. We could say that it's an error to invoke such a callback twice, but that means that all callbacks need extra logic to detect it. For async code compiled into CPS style, the same callback may be used more than once (e.g., in a loop). I prefer to say what the behavior is for a correct future or stream, and let the implementation handle the remainig cases as best-effort. I don't think it's normative. Saying that something isn't specified is wrong if it is actually specified, and it's redundant if it isn't specified anywhere. Being redundant, I think it's normative. That said, I've updated the wording to be less intimidating. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:5913: If $r$ is \FALSE{}, then execution of the while statement completes normally On 2016/11/23 16:26:41, eernst wrote: > Prepend `\LMHash{}` Done. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:5916: Otherwise $r$ is \TRUE{} and then the statement $\{s\}$ is executed. On 2016/11/23 16:26:41, eernst wrote: > Prepend `\LMHash{}` Done. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:5918: If the execution breaks without a label, execution of the while statement completes normally. Indeed - it's not necessary here because the labeled statement handles it. The while statement only needs to know about the label for continues. Commentary added. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:6061: against a the value of a variable $id$ proceeds as follows: On 2016/11/23 16:26:40, eernst wrote: > Typo: spurious `a`. Done. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:6167: let $h$ be the smallest number such that $h \ge i$ and $s_h$ is non-empty. If no such $h$ exists, and let $h = n + 1$ if the \SWITCH{} statement has a \DEFAULT{}, otherwise let $h = n$. Yes, I think it's just a spurious and. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:6231: A set of \ON{}-\CATCH{} clauses, each of which specifies (either explicitly or implicitly) the type of exception object to be handled, two exception parameters and a block statement. On 2016/11/23 16:26:42, eernst wrote: > I think we need to keep `one or two` exception parameters here, because this is > about the syntax that programmers can use. We will use the equivalence below to > explain why it is enough to _specify_ the form that has two exception > parameters. Done. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:6276: Otherwise if execution of $b$ threw (\ref{completion}), the \TRY{} statement completes in the same way as the matching against the \ON{}-\CATCH{} clauses . On 2016/11/23 16:26:42, eernst wrote: > Spurious space before period. Done. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:6282: It is a static warning if $T_i$, $1 \le i \le n$ is a deferred or malformed type. Good question. The original had \commentary { It is of course a static warning if $T$ is a deferred or malformed type. } so I guess I just adapted that. Removing the commentary. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:6404: then execution of $s$ completes normally, On 2016/11/23 16:26:41, eernst wrote: > Ah! Now I can see why there was no need to have `breaks with a label that > prefixes <blah>`. Acknowledged. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:6563: Otherwise, $x$, or $e$ with $t$, are added to the stream associated with $m$ in the order they appears in $o$. The function $m$ may suspend. On 2016/11/24 11:56:28, eernst wrote: > Typo: `appears` --> `appear` Done.
Description was changed from ========== Change how the language specification describes control flow. Changed to compositionally describing how an expression or statement can complete (normally, throw, return, break, continue), and propagating the completion to the surrounding statements handling those behaviors. This should not change the current behavior except in a few cases where the existing specification was vague, misleading or just wrong. Actual changes: - The super call in an initializer list is now always called at the end, even if it is allowed to be written earlier. This matches existing VM behavior. Initialization of initializer expressions are specified as part of constructor execution, not something happening at the `new` operator. - The cancel call to a stream subscription when exiting an async for-in loop is now made explicit, and its returned future is explicitly awaited for. Previously it was unclear what happened with that future. - Pausing a surrounding async-for loop has been added everywhere the body of the loop can suspend, just before the suspension. The loop subscription is not resumed until reaching the end of the body, which is equivalent to resuming it after each suspend and then pausing it again when the synchronous execution reaches the next suspend. So, easier and doesn't change the behavior of the loop itself, but it's a visible change if you check the onPause/onResume of the loop stream. Spec now recognizes that the pause call may throw on an invalid implementation of StreamSubscription. Addresses issues #25859, #25856, #25850, #25848, #25847, #25749, #25634, #25539, #25421, #25412, #25381, #25234, #25005, #24859, #24748, #23779, #23700, #23628, #22908, #21858 (and likely more). BUG= http://dartbug.com/25859 http://dartbug.com/25856 http://dartbug.com/25850 http://dartbug.com/25848 http://dartbug.com/25847 http://dartbug.com/25749 http://dartbug.com/25634 http://dartbug.com/25539 http://dartbug.com/25421 http://dartbug.com/25412 http://dartbug.com/25381 http://dartbug.com/25234 http://dartbug.com/25005 http://dartbug.com/24859 http://dartbug.com/24748 http://dartbug.com/23779 http://dartbug.com/23700 http://dartbug.com/23628 http://dartbug.com/22908 http://dartbug.com/21858 ========== to ========== Change how the language specification describes control flow. Changed to compositionally describing how an expression or statement can complete (normally, throw, return, break, continue), and propagating the completion to the surrounding statements handling those behaviors. This should not change the current behavior except in a few cases where the existing specification was vague, misleading or just wrong. Actual changes: - The super call in an initializer list is now always called at the end, even if it is allowed to be written earlier. This matches existing VM behavior. Initialization of initializer expressions are specified as part of constructor execution, not something happening at the `new` operator. - The cancel call to a stream subscription when exiting an async for-in loop is now made explicit, and its returned future is explicitly awaited for. Previously it was unclear what happened with that future. - Pausing a surrounding async-for loop has been added everywhere the body of the loop can suspend, just before the suspension. The loop subscription is not resumed until reaching the end of the body, which is equivalent to resuming it after each suspend and then pausing it again when the synchronous execution reaches the next suspend. So, easier and doesn't change the behavior of the loop itself, but it's a visible change if you check the onPause/onResume of the loop stream. Spec now recognizes that the pause call may throw on an invalid implementation of StreamSubscription. Addresses issues #25859, #25856, #25850, #25848, #25847, #25749, #25634, #25539, #25421, #25412, #25381, #25234, #25005, #24859, #24748, #23779, #23700, #23628, #22908, #21858 (and likely more). BUG= http://dartbug.com/25859 http://dartbug.com/25856 http://dartbug.com/25850 http://dartbug.com/25848 http://dartbug.com/25847 http://dartbug.com/25749 http://dartbug.com/25634 http://dartbug.com/25539 http://dartbug.com/25421 http://dartbug.com/25412 http://dartbug.com/25381 http://dartbug.com/25234 http://dartbug.com/25005 http://dartbug.com/24859 http://dartbug.com/24748 http://dartbug.com/23779 http://dartbug.com/23700 http://dartbug.com/23628 http://dartbug.com/22908 http://dartbug.com/21858 R=eernst@google.com Committed: https://github.com/dart-lang/sdk/commit/843bb96813f9a171c7257fcd5e282ff1d323c53d ==========
Message was sent while issue was closed.
Committed patchset #14 (id:260001) manually as 843bb96813f9a171c7257fcd5e282ff1d323c53d (presubmit successful).
Message was sent while issue was closed.
Just acknowledging the final comments. https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... File docs/language/dartLangSpec.tex (right): https://codereview.chromium.org/2399343002/diff/180001/docs/language/dartLang... docs/language/dartLangSpec.tex:5858: loop is unspecified. On 2016/11/25 08:30:35, Lasse Reichstein Nielsen wrote: > (1) Sure it does. For example, it doesn't say how "await" waits for a future to > complete. It must be done by adding a `then` listener and either an onError > callback on the then or a catchError call to get the error. It's completely > unspecified what happens if a badly implemented future calls both callbacks or > calls one of the callbacks twice. > The problem is generally with the specification handing out callbacks and making > *any* assumption about how they are invoked. > > It's hard to avoid that problem completely without overspecifying the semantics > and adding significant overhead to implementations, and for no practical reason > in all but completely borked programs. > > We could say that it's an error to invoke such a callback twice, but that means > that all callbacks need extra logic to detect it. For async code compiled into > CPS style, the same callback may be used more than once (e.g., in a loop). I > prefer to say what the behavior is for a correct future or stream, and let the > implementation handle the remainig cases as best-effort. > > > I don't think it's normative. Saying that something isn't specified is wrong if > it is actually specified, and it's redundant if it isn't specified anywhere. > Being redundant, I think it's normative. > That said, I've updated the wording to be less intimidating. OK, acknowledged! |