Skip to content

Commit

Permalink
Specify yield* and await for in more detail.
Browse files Browse the repository at this point in the history
  • Loading branch information
lrhn committed Mar 16, 2021
1 parent 893d59b commit 0b2243e
Showing 1 changed file with 76 additions and 34 deletions.
110 changes: 76 additions & 34 deletions specification/dartLangSpec.tex
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@
% - Add requirement that the iterator of a for-in statement must have
% type `Iterator`.
% - Clarify which constructors are covered by the section 'Constant
% Constructors' and removed confusing redundancy in definiton of
% Constructors' and removed confusing redundancy in definition of
% potentially constant expressions.
% - Integrate the feature specification of collection literal elements
% (aka UI-as-code).
Expand Down Expand Up @@ -1717,7 +1717,7 @@ \subsection{Function Declarations}
with the built-in identifier \STATIC{}.

\LMHash{}%
When we say that a function $f_1$ \Index{forwards} to another function $f_2$,
When we say that a function $f_1$ \Index{forwards} to another function $f_2$,
we mean that invoking $f_1$ causes $f_2$ to be executed
with the same arguments and/or receiver as $f_1$,
and returns the result of executing $f_2$ to the caller of $f_1$,
Expand Down Expand Up @@ -1952,7 +1952,7 @@ \subsubsection{Optional Formals}
callers from outside the library where it was defined.
If a method outside the library overrode a method with a private optional name,
it would not be a subtype of the original method.
The static checker would of course flag such situations,
The static checker would of course flag such situations,
but the consequence would be that adding a private named formal would break
clients outside the library in a way they could not easily correct.%
}
Expand Down Expand Up @@ -3432,7 +3432,7 @@ \subsubsection{Generative Constructors}
\commentary{%
This means that formal parameters, including initializing formals,
must have distinct names, and that initializing formals
are in scope for the initializer list,
are in scope for the initializer list,
but they are not in scope for the body of the constructor.
When a formal parameter introduces a local variable into two scopes,
it is still one variable and hence one storage location.
Expand Down Expand Up @@ -5230,7 +5230,7 @@ \subsection{Mixin Classes}
% to be compile-time errors.

\commentary{%
It is an error, for example, if $M$ contains a member declaration $d$
It is an error, for example, if $M$ contains a member declaration $d$
which overrides a member signature $m$ in the interface of $S$,
but which is not a correct override of $m$
(\ref{correctMemberOverrides}).%
Expand Down Expand Up @@ -8254,7 +8254,7 @@ \subsection{Constants}
% be computed statically without running user code.

% A validly typed potentially constant expression can still fail when evaluated.
% If that happens in a const invociation, it's a compile-time error.
% If that happens in a const invocation, it's a compile-time error.

\LMHash{}%
It is a compile-time error if an expression is required to be
Expand Down Expand Up @@ -13772,7 +13772,7 @@ \subsubsection{Sending Messages}
Messages are sent by invoking specific methods in the Dart libraries; there is no specific syntax for sending a message.

\commentary{%
In other words, the methods supporting sending messages
In other words, the methods supporting sending messages
embody primitives of Dart that are not accessible to ordinary code,
much like the methods that spawn isolates.%
}
Expand Down Expand Up @@ -16880,13 +16880,13 @@ \subsection{If}

\rationale{%
Under reasonable scope rules such code is problematic.
If we assume that \code{v} is declared
in the scope of the method \code{main()},
then when \code{somePredicate} is false,
If we assume that \code{v} is declared
in the scope of the method \code{main()},
then when \code{somePredicate} is false,
\code{v} will be uninitialized when accessed.
The cleanest approach would be to require a block following the test,
The cleanest approach would be to require a block following the test,
rather than an arbitrary statement.
However, this goes against long standing custom,
However, this goes against long standing custom,
undermining Dart's goal of familiarity.
Instead, we choose to insert a block, introducing a scope,
around the statement following the predicate
Expand Down Expand Up @@ -17141,7 +17141,7 @@ \subsubsection{Asynchronous For-in}
It is a compile-time error if a traditional for loop (\ref{forLoop}) is prefixed by the \AWAIT{} keyword.

\rationale{%
An asynchronous loop would make no sense within a synchronous function,
An asynchronous loop would make no sense within a synchronous function,
for the same reasons that an await expression makes no sense
in a synchronous function.%
}
Expand Down Expand Up @@ -18083,7 +18083,8 @@ \subsection{Yield-Each}
if the class of $o$ is not a subtype of \code{Iterable<$T_f$>}.
Otherwise
\item
The method \code{iterator} is invoked upon $o$ returning an object $i$.
The getter \code{iterator} is invoked upon $o$ returning an object $i$.
Otherwise
\item
\label{moveNext} The \code{moveNext} method of $i$ is invoked on it
with no arguments.
Expand Down Expand Up @@ -18117,35 +18118,76 @@ \subsection{Yield-Each}
It is a dynamic type error if the class of $o$
is not a subtype of \code{Stream<$T_f$>}.
Otherwise
\item
If the stream associated with $m$ has been cancelled,
then execution of $s$ completes by returning without a value.
\commentary{In this case, the \code{\YIELD*} operation does
not begin to listen to the stream $o$.}
Otherwise
\item
The $o$ stream is listened to by invoking \code{$v_o$.listen}
with system provided arguments,
where $v_o$ is a fresh variable referencing the stream $o$.
Let $u$ be the stream subscription returned by the call to
\code{$p$.listen} and let $v$ be a fresh variable bound to $u$.
\item
If the stream associated with $m$ is paused, then $u$ is immediately
paused as if by invoking \code{$v$.pause} with no arguments.
\item{}
If the stream associated with $m$ has been cancelled, then
$u$ is cancelled by executing \code{await $v$.cancel();}.
If this execution does not throw, the execution of $s$
completes by returning without a value.
% This can only happen if a call to "listen" or "pause" above has
% side effects which cancels the stream of $m$.
\item
The nearest enclosing asynchronous for loop (\ref{asynchronousFor-in}),
if any, is paused.
\item
The $o$ stream is listened to, creating a subscription $s$,
and for each event $x$, or error $e$ with stack trace $t$, of $s$:
Execution of $m$ is suspended.
While $m$ is suspended, the following reactions happen if $u$ delivers
an event or if the stream associated with $m$ is paused, resumed or cancelled.
\commentary{It is unspecified what happens if $u$ delivers events
before $m$ is suspended or after $m$ is resumed, or if $u$ delivers events
after a call to \code{$v$.cancel} or a call to \code{$v$.pause} which has
not been followed by a call to \code{$v$.resume}, or after having delivered
a done event.}
% Such events should be ignored.
\begin{itemize}
\item
If the stream $u$ associated with $m$ has been paused,
then execution of $m$ is suspended until $u$ is resumed or canceled.
If the stream associated with $m$ becomes paused,
then $u$ is paused by executing \code{$v$.pause();}.
It is unspecified what happens if this execution throws.
% The error can be passed to \code{Zone.current.handleUncaughtError}.
\item
If the stream $u$ associated with $m$ has been canceled,
then $s$ is canceled by evaluating \code{\AWAIT{} v.cancel()}
where $v$ is a fresh variable referencing the stream subscription $s$.
Then, if the cancel completed normally,
the stream execution of $s$ returns without an object
(\ref{statementCompletion}).
If the stream associated with $m$ is resumed after being paused,
then $u$ is resumed as by executing \code{$v$.resume();}.
It is unspecified what happens if this execution throws.
% The error can be passed to \code{Zone.current.handleUncaughtError}.
\item
If the stream associated with $m$ is cancelled,
then $u$ is also cancelled as by executing \code{await $v$.cancel();}.

At some future time, execution of $m$ resumes. If the execution above
completed by throwing an error \metavar{er} and stack trace \metavar{st},
then execution of $s$ completes by throwing \metavar{er}
and stack trace \metavar{st}.
Otherwise, execution of $s$ completes by returning without a value.
\item
Otherwise, $x$, or $e$ with $t$, are added to
the stream associated with $m$ in the order they appear in $o$.
\commentary{%
Note that a dynamic error occurs if $x$ is added
and the dynamic type of $x$ is not a subtype of
the element type of said stream.%
}
The function $m$ may suspend.
If $u$ emits a data event with value $x$,
then if the runtime type of $x$ is not a subtype of $T_v$,
then the stream associated with $m$ emits a dynamic type error.
Otherwise the stream associated with $m$ immediately emits
a data event with value $x$.
\item
If $u$ emits an error event with error \metavar{er}
and stack trace \metavar{st},
then the stream associated with $m$ immediately emits an error event
with error \metavar{er} and stack trace \metavar{st}.
\item
If $u$ closes \commentary{(by emitting a done event)},
then execution of $m$ resumes and execution of $s$ completes normally.
\end{itemize}
\item
If the stream $o$ is done, execution of $s$ completes normally.
\end{itemize}


Expand Down

0 comments on commit 0b2243e

Please sign in to comment.