Chromium Code Reviews| Index: docs/language/dartLangSpec.tex |
| =================================================================== |
| --- docs/language/dartLangSpec.tex (revision 44569) |
| +++ docs/language/dartLangSpec.tex (working copy) |
| @@ -37,7 +37,7 @@ |
| A conforming implementation of the Dart programming language must provide and support all the APIs (libraries, types, functions, getters, setters, whether top-level, static, instance or local) mandated in this specification. |
| \LMHash{} |
| -A conforming implementation is permitted to provide additional APIs, but not additional syntax. |
| +A conforming implementation is permitted to provide additional APIs, but not additional syntax, except for experimental features in support of null-aware cascades and tear-offs that are likely to be introduced in the next revision of this specification. |
|
Lasse Reichstein Nielsen
2015/03/26 10:38:48
Clever :)
eernst
2015/03/26 22:38:50
I guess 'property extraction' covers more than int
|
| \section{Normative References} |
| \LMLabel{ecmaNormativeReferences} |
| @@ -2349,6 +2349,8 @@ |
| literal; |
| identifier; |
| newExpression; |
| + \NEW{} type `\#' (`{\escapegrammar .}' identifier)?; |
| + \CONST{} type `\#' (`{\escapegrammar .}' identifier)?; |
|
Paul Berry
2015/03/26 18:55:58
What's the justification for having tear-offs of b
Lasse Reichstein Nielsen
2015/03/26 19:18:57
Ack, yes, forgot to comment on that.
If there is n
eernst
2015/03/26 22:38:51
Did you have to add the periods here to make the g
gbracha
2015/03/26 23:21:22
You mean we haven't stated that a const T# is a co
|
| constObjectExpression; |
| `(' expression `)' |
| . |
| @@ -3525,11 +3527,14 @@ |
| } |
| \LMHash{} |
| -If $f$ is asynchronous then, when $f$ terminates, any open stream subscriptions associated with any asynchronous for loops (\ref{asynchronousFor-in}) or yield-each statements (\ref{yieldEach}) executing within $f$ are canceled. |
| +If $f$ is asynchronous then, when $f$ terminates, any open stream subscriptions associated with any asynchronous for loops (\ref{asynchronousFor-in}) or yield-each statements (\ref{yieldEach}) executing within $f$ are canceled, in the order of their nesting, innermost first. |
| \rationale{Such streams may be left open by for loops that were escaped when an exception was thrown within them for example. |
| } |
| +%\LMHash{} |
| +%When a stream is canceled, the implementation must wait for the cancelation future returned by \cd{cancell()} to complete before proceeding. |
|
Lasse Reichstein Nielsen
2015/03/26 10:38:48
Uncomment?
Also maybe: "stream is canceled" -> "st
gbracha
2015/03/26 23:21:22
The VM team has concerns with this. If it's absenc
|
| + |
| \LMHash{} |
| If $f$ is marked \SYNC* (\ref{functions}), then a fresh instance $i$ implementing the built-in class \code{Iterable} is associated with the invocation and immediately returned. |
| @@ -3775,12 +3780,30 @@ |
| \LMLabel{ordinaryInvocation} |
| \LMHash{} |
| -An ordinary method invocation $i$ has the form |
| +An ordinary method invocation can be {\em conditional} or {\em unconditional}. |
| +\LMHash{} |
| +Evaluation of a {\em conditional ordinary method invocation} $e$ of the form |
| + |
| +\LMHash{} |
| +$o?.m(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ |
| + |
| +\LMHash{} |
| +is equivalent to the evaluation of the expression |
| + |
| +\LMHash{} |
| +$((x) => x == \NULL ? \NULL : x.im(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k}))(o)$. |
|
Lasse Reichstein Nielsen
2015/03/26 10:38:48
x.im -> x.m
Lasse Reichstein Nielsen
2015/03/26 10:38:48
Does this correctly give static warnings if o.m do
Paul Berry
2015/03/26 15:07:21
Unfortunately Lasse's proposed rewrite would intro
gbracha
2015/03/26 23:21:21
Done.
gbracha
2015/03/26 23:21:23
No, because checked mode would behave differently.
|
| + |
| +\LMHash{} |
| +The static type of $e$ is the same as the static type of $o.m(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$. |
| + |
| +\LMHash{} |
| +An {\em unconditional ordinary method invocation} $i$ has the form |
| + |
| $o.m(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$. |
| \LMHash{} |
| -Evaluation of an ordinary method invocation $i$ of the form |
| +Evaluation of an unconditional ordinary method invocation $i$ of the form |
| $o.m(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ |
| @@ -3876,6 +3899,12 @@ |
| \LMHash{} |
| A cascaded method invocation expression of the form {\em e..suffix} is equivalent to the expression \code{(t)\{t.{\em suffix}; \RETURN{} t;\}($e$)}. |
| +\rationale{ |
| +With the introduction of null-aware conditional assignable expressions (\ref{assignableExpressions}), it would make sense to extend cascades with a null-aware conditional form as well. One might define {\em e?..suffix} to be equivalent to the expression \code{(t)\{t?.{\em suffix}; \RETURN{} t;\}($e$)}. |
|
Lasse Reichstein Nielsen
2015/03/26 10:38:48
Makes sense. We have cascades so you can write x..
eernst
2015/03/26 22:38:51
Having x?..foo?..bar it's natural to consider x?..
|
| + |
| +The present specification has not added such a construct, in the interests of simplicity and rapid language evolution. However, Dart implementations may experiment with such constructs, as noted in section \ref{ecmaConformance}. |
| +} |
| + |
| \subsubsection{Super Invocation} |
| \LMLabel{superInvocation} |
| @@ -3946,21 +3975,32 @@ |
| \LMLabel{propertyExtraction} |
| \LMHash{} |
| -{\em Property extraction} allows for a member of an object to be concisely extracted from the object. |
| +{\em Property extraction} allows for a member or constructor to be accessed as a property rather than a function. |
| A property extraction can be either: |
| \begin{enumerate} |
| -\item A {\em closurization} (\ref{closurization}) which allows a method to be treated as if it were a getter for a function valued object. Or |
| +\item A {\em closurization} which converts a method or constructor into a closure. Or |
| \item A {\em getter invocation} which returns the result of invoking of a getter method. |
| \end{enumerate} |
| \LMHash{} |
| +Property extraction takes several syntactic forms: $e.m$ (\ref{getterAccessAndMethodExtraction}), $\SUPER.m$ (\ref{superGetterAccessAndMethodClosurization}), $e\#m$ (\ref{generalClosurization}), $\NEW{}$ $T\#m$ (\ref{namedConstructorExtraction}), $\NEW{}$ $T\#$ (\ref{anonymousConstructorExtraction}) and $\SUPER\#m$ (\ref{generalSuperPropertyExtraction}), where $e$ is an expression, $m$ is an identifier optionally followed by an equal sign and $T$ is a type. |
|
Paul Berry
2015/03/26 15:07:21
As I mentioned on line 3704, I think the syntactic
gbracha
2015/03/26 23:21:22
super?.m makes no sense; I've altered the grammar
|
| + |
| +\subsubsection{Getter Access and Method Extraction} |
| +\LMLabel{getterAccessAndMethodExtraction} |
| + |
| +\LMHash{} |
| Evaluation of a property extraction $i$ of the form $e.m$ proceeds as follows: |
| \LMHash{} |
| -First, the expression $e$ is evaluated to an object $o$. Let $f$ be the result of looking up (\ref{methodLookup}) method (\ref{instanceMethods}) $m$ in $o$ with respect to the current library $L$. If $o$ is an instance of \code{Type} but $e$ is not a constant type literal, then if $m$ is a method that forwards (\ref{functionDeclarations}) to a static method, method lookup fails. If method lookup succeeds and $f$ is a concrete method then $i$ evaluates to the closurization of $o.m$. |
| +First, the expression $e$ is evaluated to an object $o$. Let $f$ be the result of looking up (\ref{methodLookup}) method (\ref{instanceMethods}) $m$ in $o$ with respect to the current library $L$. If $o$ is an instance of \code{Type} but $e$ is not a constant type literal, then if $f$ is a method that forwards (\ref{functionDeclarations}) to a static method, method lookup fails. If method lookup succeeds then $i$ evaluates to the closurization of method $f$ on object $o$ (\ref{ordinaryMemberClosurization}). |
| +\commentary { |
| +Note that $f$ is never an abstract method, because method lookup skips abstract methods. Hence, if $m$ refers to an abstract method, we will continue to the next step. However, since methods and getters never override each other, getter lookup will necessarily fail as well, and \cd{noSuchMethod()} will ultimately be invoked. The regrettable implication is that the error will refer to a missing getter rather than an attempt to closurize an abstract method. |
| +} |
| + |
| \LMHash{} |
| -Otherwise, $i$ is a getter invocation, and the getter function (\ref{getters}) $m$ is looked up (\ref{getterAndSetterLookup}) in $o$ with respect to $L$. If $o$ is an instance of \code{Type} but $e$ is not a constant type literal, then if $m$ is a getter that forwards to a static getter, getter lookup fails. Otherwise, the body of $m$ is executed with \THIS{} bound to $o$. The value of $i$ is the result returned by the call to the getter function. |
| +Otherwise, $i$ is a getter invocation. Let $f$ be the result of looking up |
| +(\ref{getterAndSetterLookup}) getter (\ref{getters}) $m$ in $o$ with respect to $L$. If $o$ is an instance of \code{Type} but $e$ is not a constant type literal, then if $f$ is a getter that forwards to a static getter, getter lookup fails. Otherwise, the body of $f$ is executed with \THIS{} bound to $o$. The value of $i$ is the result returned by the call to the getter function. |
| \LMHash{} |
| If the getter lookup has failed, then a new instance $im$ of the predefined class \code{Invocation} is created, such that : |
| @@ -3972,10 +4012,10 @@ |
| \end{itemize} |
| Then the method \code{noSuchMethod()} is looked up in $o$ and invoked with argument $im$, and the result of this invocation is the result of evaluating $i$. However, if the implementation found cannot be invoked with a single positional argument, the implementation of \code{noSuchMethod()} in class \code{Object} is invoked on $o$ with argument $im'$, where $im'$ is an instance of \code{Invocation} such that : |
| \begin{itemize} |
| -\item \code{im.isMethod} evaluates to \code{\TRUE{}}. |
| -\item \code{im.memberName} evaluates to \code{noSuchMethod}. |
| -\item \code{im.positionalArguments} evaluates to an immutable list whose sole element is $im$. |
| -\item \code{im.namedArguments} evaluates to the value of \code{\CONST{} \{\}}. |
| +\item \code{im'.isMethod} evaluates to \code{\TRUE{}}. |
| +\item \code{im'.memberName} evaluates to \code{noSuchMethod}. |
| +\item \code{im'.positionalArguments} evaluates to an immutable list whose sole element is $im$. |
| +\item \code{im'.namedArguments} evaluates to the value of \code{\CONST{} \{\}}. |
| \end{itemize} |
| and the result of this latter invocation is the result of evaluating $i$. |
| @@ -3996,24 +4036,27 @@ |
| \end{itemize} |
| \LMHash{} |
| -If $i$ is a getter invocation, the static type of $i$ is: |
| +The static type of $i$ is: |
| \begin{itemize} |
| -\item The declared return type of $T.m$, if $T.m$ exists. |
| -\item The declared return type of $m$, if $T$ is \code{Type}, $e$ is a constant type literal and the class corresponding to $e$ has a static method or getter named $m$. |
| +\item The declared return type of $T.m$, if $T$ has an accessible instance getter named $m$. |
| +\item The declared return type of $m$, if $T$ is \code{Type}, $e$ is a constant type literal and the class corresponding to $e$ declares an accessible static getter named $m$. |
| +\item The static type of function $T.m$ if $T$ has an accessible instance method named $m$. |
| +\item The static type of function $m$, if $T$ is \code{Type}, $e$ is a constant type literal and the class corresponding to $e$ declares an accessible static method named $m$. |
| \item The type \DYNAMIC{} otherwise. |
| \end{itemize} |
| -\LMHash{} |
| -If $i$ is a closurization, its static type is as described in section \ref{closurization}. |
| +\subsubsection{Super Getter Access and Method Closurization} |
| +\LMLabel{superGetterAccessAndMethodClosurization} |
| + |
| \LMHash{} |
| Evaluation of a property extraction $i$ of the form $\SUPER.m$ proceeds as follows: |
| \LMHash{} |
| - Let $S$ be the superclass of the immediately enclosing class. Let $f$ be the result of looking up method $m$ in $S$ with respect to the current library $L$. If $f$ is a concrete method then $i$ evaluates to the closurization of $\SUPER.m$ with respect to superclass $S$(\ref{closurization}). |
| + Let $S$ be the superclass of the immediately enclosing class. Let $f$ be the result of looking up method $m$ in $S$ with respect to the current library $L$. If method lookup succeeds then $i$ evaluates to the closurization of method $f$ with respect to superclass $S$ (\ref{superClosurization}). |
| \LMHash{} |
| - Otherwise, $i$ is a getter invocation and the getter function $m$ is looked up in $S$ with respect to $L$, and its body is executed with \THIS{} bound to the current value of \THIS{}. The value of $i$ is the result returned by the call to the getter function. |
| + Otherwise, $i$ is a getter invocation. Let $f$ be the result of looking up getter $m$ in $S$ with respect to $L$. The body of $f$ is executed with \THIS{} bound to the current value of \THIS{}. The value of $i$ is the result returned by the call to the getter function. |
| \LMHash{} |
| If the getter lookup has failed, then a new instance $im$ of the predefined class \code{Invocation} is created, such that : |
| @@ -4025,34 +4068,166 @@ |
| \end{itemize} |
| Then the method \code{noSuchMethod()} is looked up in $S$ and invoked with argument $im$, and the result of this invocation is the result of evaluating $i$. However, if the implementation found cannot be invoked with a single positional argument, the implementation of \code{noSuchMethod()} in class \code{Object} is invoked on \THIS{} with argument $im'$, where $im'$ is an instance of \code{Invocation} such that : |
| \begin{itemize} |
| -\item \code{im.isMethod} evaluates to \code{\TRUE{}}. |
| -\item \code{im.memberName} evaluates to \code{noSuchMethod}. |
| -\item \code{im.positionalArguments} evaluates to an immutable list whose sole element is $im$. |
| +\item \code{im'.isMethod} evaluates to \code{\TRUE{}}. |
| +\item \code{im'.memberName} evaluates to \code{noSuchMethod}. |
| +\item \code{im'.positionalArguments} evaluates to an immutable list whose sole element is $im$. |
| +\item \code{im'.namedArguments} evaluates to the value of \code{\CONST{} \{\}}. |
| +\end{itemize} |
| +and the result of this latter invocation is the result of evaluating $i$. |
| + |
| +\LMHash{} |
| +It is a static type warning if $S$ does not have an accessible instance method or getter named $m$. |
| + |
| +The static type of $i$ is: |
| +\begin{itemize} |
| +\item The declared return type of $S.m$, if $S$ has an accessible instance getter named $m$. |
| +\item The static type of function $S.m$ if $S$ has an accessible instance method named $m$. |
| +\item The type \DYNAMIC{} otherwise. |
| +\end{itemize} |
| + |
| + |
| +\subsubsection{General Closurization} |
| +\LMLabel{generalClosurization} |
| + |
| +\LMHash{} |
| +Evaluation of a property extraction $i$ of the form $e\#m$ proceeds as follows: |
| + |
| +\LMHash{} |
| +First, the expression $e$ is evaluated to an object $o$. Let $f$ be the result of looking up method $m$ in $o$ with respect to the current library $L$. If $o$ is an instance of \cd{Type} but $e$ is not a constant type literal, then if $f$ is a method that forwards to a static method, method lookup fails. If method lookup succeeds then $i$ evaluates to the closurization of method $f$ on object $o$ (\ref{ordinaryMemberClosurization}). |
| + |
| +\LMHash{} |
| + Otherwise, let $f$ be the result of looking up getter $m$ in $o$ with respect to the current library $L$. If $o$ is an instance of \cd{Type} but $e$ is not a constant type literal, then if $f$ is a method that forwards to a static getter, getter lookup fails. If getter lookup succeeds then $i$ evaluates to the closurization of getter $f$ on object $o$ (\ref{ordinaryMemberClosurization}). |
| + |
| + \LMHash{} |
| + Otherwise, let $f$ be the result of looking up setter $m$ in $o$ with respect to the current library $L$. If $o$ is an instance of \cd{Type} but $e$ is not a constant type literal, then if $f$ is a method that forwards to a static setter, setter lookup fails. If setter lookup succeeds then $i$ evaluates to the closurization of setter $f$ on object $o$ (\ref{ordinaryMemberClosurization}). |
|
Lasse Reichstein Nielsen
2015/03/26 10:38:48
So we technically go through the previous two look
sra1
2015/03/26 19:41:38
It seems that this would be simpler if the closuri
gbracha
2015/03/26 23:21:22
Yes, I think splitting it makes a lot of sense, fo
|
| + |
| + |
| +\LMHash{} |
| +Otherwise, a new instance $im$ of the predefined class \code{Invocation} is created, such that : |
| +\begin{itemize} |
| +\item If $m$ is a setter name, \code{im.isSetter} evaluates to \code{\TRUE{}}; otherwise \code{im.isMethod} evaluates to \code{\TRUE{}} |
|
Lasse Reichstein Nielsen
2015/03/26 10:38:48
I still think this is dangerously wrong, and must
sra1
2015/03/26 19:41:38
I think this would also be fixed by e#foo / e#get
Lasse Reichstein Nielsen
2015/03/26 20:23:23
I don't see how that would change anything. There
gbracha
2015/03/26 23:21:22
Good point. Indeed, existing tear-offs using the e
Lasse Reichstein Nielsen
2015/03/27 07:03:04
The existing extraction works because of the corre
|
| +\item \code{im.memberName} evaluates to \code{'m'}. |
|
Lasse Reichstein Nielsen
2015/03/26 10:38:48
This looks like it evaluates to a string, but it s
gbracha
2015/03/26 23:21:22
A bug that has been lying dormant for a while. Fix
|
| +\item \code{im.positionalArguments} evaluates to the value of \code{\CONST{} []}. |
|
Lasse Reichstein Nielsen
2015/03/26 10:38:48
Are we requiring "const []" in other places too? O
eernst
2015/03/26 22:38:50
Why not \code{\CONST{} <Object>[]}, such that List
gbracha
2015/03/26 23:21:22
We have been doing this in similar situations with
|
| \item \code{im.namedArguments} evaluates to the value of \code{\CONST{} \{\}}. |
| \end{itemize} |
| - |
| +Then the method \code{noSuchMethod()} is looked up in $o$ and invoked with argument $im$, and the result of this invocation is the result of evaluating $i$. However, if the implementation found cannot be invoked with a single positional argument, the implementation of \code{noSuchMethod()} in class \code{Object} is invoked on $o$ with argument $im'$, where $im'$ is an instance of \code{Invocation} such that : |
| +\begin{itemize} |
| +\item \code{im'.isMethod} evaluates to \code{\TRUE{}}. |
| +\item \code{im'.memberName} evaluates to \code{noSuchMethod}. |
|
Lasse Reichstein Nielsen
2015/03/26 10:38:48
Symbol #noSuchMethod ?
gbracha
2015/03/26 23:21:22
Done everywhere in response to previous comment.
|
| +\item \code{im'.positionalArguments} evaluates to an immutable list whose sole element is $im$. |
| +\item \code{im'.namedArguments} evaluates to the value of \code{\CONST{} \{\}}. |
|
eernst
2015/03/26 22:38:50
Could again be <Object>[$im$] and \CONST <Object>\
|
| +\end{itemize} |
| and the result of this latter invocation is the result of evaluating $i$. |
| \LMHash{} |
| -It is a static type warning if $S$ does not have a method or getter named $m$. If $i$ is a getter invocation, the static type of $i$ is the declared return type of $S.m$, if $S.m$ exists and \DYNAMIC{} otherwise. If $i$ is a closurization, its static type is as described in section \ref{closurization}. |
| +It is a compile-time error if $e$ is a prefix object (\ref{imports}) and $m$ refers to a type or a member of class \cd{Object}. |
| +\commentary{ |
| +This restriction is in line with other limitations on the use of prefixes as objects. The only permitted uses of $p\#m$ are closurizing top level methods and getters imported via the prefix $p$. Top level methods are directly available by their qualified names: $p.m$. However, getters and setters are not, and allowing their closurization is the whole point of the $e\#m$ syntax. |
| +} |
| -\subsubsection{Closurization} |
| -\LMLabel{closurization} |
| +\LMHash{} |
| +Let $T$ be the static type of $e$. It is a static type warning if $T$ does not have an accessible instance method or getter named $m$ unless either: |
|
Paul Berry
2015/03/26 18:55:58
It seems inconsistent that on line 4102 we allow e
|
| +\begin{itemize} |
| +\item $T$ or a superinterface of $T$ is annotated with an annotation denoting a constant identical to the constant proxy defined in \cd{dart:core}. Or |
|
Paul Berry
2015/03/26 18:55:58
Nit: when this text appears elsewhere in the spec,
|
| +\item $T$ is \cd{Type}, $e$ is a constant type literal and the class corresponding to $e$ declares an accessible static method or getter named $m$. |
|
Paul Berry
2015/03/26 18:55:58
Similarly, "or setter" should be added here.
|
| +\end{itemize} |
| +The static type of $i$ is: |
| +\begin{itemize} |
| +\item The static type of function $T.m$, if $T$ has an accessible instance member named $m$. |
| +\item The static type of function $T.m$, if $T$ is \cd{Type}, $e$ is a constant type literal and the class corresponding to $e$ declares an accessible static member or constructor named $m$. |
| +\item The type \DYNAMIC{} otherwise. |
| +\end{itemize} |
|
Paul Berry
2015/03/26 18:55:58
Consider adding some non-normative explanatory tex
|
| + |
| +\subsubsection{Named Constructor Extraction} |
| +\LMLabel{namedConstructorExtraction} |
| + |
| \LMHash{} |
| -The {\em closurization of $o.m$} is defined to be equivalent to: |
| +Evaluation of a property extraction $i$ of the form \NEW{} $T\#m$ or \CONST{} $T\#m$ proceeds as follows: |
|
Paul Berry
2015/03/26 18:55:58
This is inconsistent with line 2352, where the con
|
| +\LMHash{} |
| +If $T$ is a malformed type (\ref{staticTypes}), a dynamic error occurs. If $T$ is a deferred type with prefix $p$, then if $p$ has not been successfully loaded, a dynamic error occurs. If $T$ does not denote a class, a dynamic error occurs. In checked mode, if $T$ or any of its superclasses is malbounded a dynamic error occurs. Otherwise, if the type $T$ does not declare an accessible named constructor $f$ with name $m$, a \cd{NoSuchMethodError} is thrown. Otherwise, $i$ evaluates to the closurization of constructor $f$ of type $T$ (\ref{namedConstructorClosurization}). |
| + |
| +\commentary{Note that if $T$ is malformed or malbounded, a static warning occurs, as always.} |
| + |
| +\LMHash{} |
| +The static type of $i$ is the type of the constructor function, if $T$ denotes a class in the surrounding scope with an accessible constructor $f$ named $m$. Otherwise the static type of $i$ is \DYNAMIC{}. |
|
Paul Berry
2015/03/26 18:55:58
"$f$" can be removed, since nothing refers to it.
|
| + |
| +\subsubsection{Anonymous Constructor Extraction} |
| +\LMLabel{anonymousConstructorExtraction} |
| + |
| +\LMHash{} |
| +Evaluation of a property extraction $i$ of the form \NEW{} $T\#$ or \CONST{} $T\#$ proceeds as follows: |
| + |
| +\LMHash{} |
| +If $T$ is a malformed type (\ref{staticTypes}), a dynamic error occurs. If $T$ is a deferred type with prefix $p$, then if $p$ has not been successfully loaded, a dynamic error occurs. If $T$ does not denote a class, a dynamic error occurs. In checked mode, if $T$ or any of its superclasses is malbounded a dynamic error occurs. Otherwise, if the type $T$ does not declare an accessible anonymous constructor, a \cd{NoSuchMethodError} is thrown. Otherwise, $i$ evaluates to the closurization of the anonymous constructor of type $T$ (\ref{anonymousConstructorClosurization}). |
| + |
| +\commentary{Again, note that if $T$ is malformed or malbounded, existing rules ensure that a static warning occurs. This also means that $x\#$ where $x$ is not a type will always give a static warning.} |
|
Paul Berry
2015/03/26 18:55:58
I think you mean "This also means that \NEW{} $x\#
|
| + |
| +\LMHash{} |
| +The static type of $i$ is the type of the constructor function $T()$, if $T$ denotes a class in the surrounding scope with an anonymous constructor $T()$. Otherwise the static type of $i$ is \DYNAMIC{}. |
| + |
| +\subsubsection{General Super Property Extraction} |
| +\LMLabel{generalSuperPropertyExtraction} |
| + |
| + |
| +\LMHash{} |
| +Evaluation of a property extraction $i$ of the form \SUPER$\#m$ proceeds as follows: |
| + |
| +Let $S$ be the superclass of the immediately enclosing class. Let $f$ be the result of looking up method $m$ in $S$ with respect to the current library $L$. If method lookup succeeds then $i$ evaluates to the closurization of method $m$ with respect to superclass $S$ (\ref{superClosurization}). |
| + |
| +\LMHash{} |
| + Otherwise, let $f$ be the result of looking up getter $m$ in $S$ with respect to the current library $L$. If getter lookup succeeds then $i$ evaluates to the closurization of getter $f$ with respect to superclass $S$ (\ref{superClosurization}). |
| + |
| + \LMHash{} |
| + Otherwise, let $f$ be the result of looking up setter $m$ in $S$ with respect to the current library $L$. If setter lookup succeeds then $i$ evaluates to the closurization of setter $f$ with respect to superclass $S$ (\ref{superClosurization}). |
| + |
| + |
| +\LMHash{} |
| +Otherwise, a new instance $im$ of the predefined class \code{Invocation} is created, such that : |
| \begin{itemize} |
| +\item If $m$ is a setter name, \code{im.isSetter} evaluates to \code{\TRUE{}}; otherwise \code{im.isMethod} evaluates to \code{\TRUE{}} |
|
Lasse Reichstein Nielsen
2015/03/26 10:38:48
Same comment as above: Just throw a NoSuchMethodEr
gbracha
2015/03/26 23:21:21
Done.
|
| +\item \code{im.memberName} evaluates to \code{'m'}. |
| +\item \code{im.positionalArguments} evaluates to the value of \code{\CONST{} []}. |
| +\item \code{im.namedArguments} evaluates to the value of \code{\CONST{} \{\}}. |
|
eernst
2015/03/26 22:38:50
Again we could have <Object>[] and <Object>{}.
|
| +\end{itemize} |
| +Then the method \code{noSuchMethod()} is looked up in $S$ and invoked with argument $im$, and the result of this invocation is the result of evaluating $i$. However, if the implementation found cannot be invoked with a single positional argument, the implementation of \code{noSuchMethod()} in class \code{Object} is invoked on \THIS{} with argument $im'$, where $im'$ is an instance of \code{Invocation} such that : |
| +\begin{itemize} |
| +\item \code{$im'$.isMethod} evaluates to \code{\TRUE{}}. |
| +\item \code{$im'$.memberName} evaluates to \code{noSuchMethod}. |
| +\item \code{$im'$.positionalArguments} evaluates to an immutable list whose sole element is $im$. |
| +\item \code{$im'$.namedArguments} evaluates to the value of \code{\CONST{} \{\}}. |
|
eernst
2015/03/26 22:38:51
<Object>{}.
|
| +\end{itemize} |
| +and the result of this latter invocation is the result of evaluating $i$. |
| +\LMHash{} |
| +It is a static type warning if $S$ does not have an accessible instance member named $m$. |
| + |
| +\LMHash{} |
| +The static type of $i$ is the static type of the function $S.m$, if $S$ has an accessible instance member named $m$. Otherwise the static type of $i$ is \DYNAMIC{}. |
| + |
| + |
| + |
| +\subsubsection{Ordinary Member Closurization} |
| +\LMLabel{ordinaryMemberClosurization} |
| + |
| + |
| +\LMHash{} |
| +Let $o$ be an object, and let $u$ be a fresh final variable bound to $o$. |
| +The {\em closurization of method $f$ on object $o$} is defined to be equivalent to: |
| +\begin{itemize} |
| +\item $(a) \{\RETURN{}$ $u$ $m$ $a;$\} if $f$ is named $m$ and $m$ is one of \code{$<$, $>$, $<$=, $>$=, ==, -, +, /, \~{}/, *, \%, $|$, \^{}, \&, $<<$, $>>$} (this precludes closurization of unary -). |
| +\item $() \{\RETURN{}$ \~{} $u;$\} if $f$ is named \~{}. |
| +\item $(a) \{\RETURN{}$ $u[a];$\} if $f$ is named $[]$. |
| +\item $(a, b) \{\RETURN{}$ $u[a] = b;$\} if $f$ is named $[]=$. |
| \item |
| \begin{dartCode} |
| $(r_1, \ldots, r_n, \{p_1 : d_1, \ldots , p_k : d_k\})$ \{ |
| \RETURN{} $ u.m(r_1, \ldots, r_n, p_1: p_1, \ldots, p_k: p_k);$ |
| \} |
| \end{dartCode} |
| - |
| -if $m$ has required parameters $r_1, \ldots, r_n$, and named parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$. |
| +if $f$ is named $m$ and has required parameters $r_1, \ldots, r_n$, and named parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$. |
| \item |
| \begin{dartCode} |
| $(r_1, \ldots, r_n, [p_1 = d_1, \ldots , p_k = d_k])$\{ |
| @@ -4060,15 +4235,19 @@ |
| \} |
| \end{dartCode} |
| -if $m$ has required parameters $r_1, \ldots, r_n$, and optional positional parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$. |
| +if $f$ is named $m$ and has required parameters $r_1, \ldots, r_n$, and optional positional parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$. |
| \end{itemize} |
| -where $u$ is a fresh final variable bound to $o$, except that: |
| -\begin{enumerate} |
| -\item Iff \code{identical($o_1, o_2$)} then \cd{$o_1.m$ == $o_2.m$}. |
| -\item The static type of the property extraction is the static type of function $T.m$, where $T$ is the static type of $e$, if $T.m$ is defined. Otherwise the static type of $e.m$ is \DYNAMIC{}. |
| -\end{enumerate} |
| +\LMHash{} |
| +Except that iff \code{identical($o_1, o_2$)} then \cd{$o_1\#m$ == $o_2\#m$}, \cd{$o_1.m$ == $o_2.m$}, \cd{$o_1\#m$ == $o_2.m$} and \cd{$o_1.m$ == $o_2\#m$}. |
| +%\item The static type of the property extraction is the static type of function $T.m$, where $T$ is the static type of $e$, if $T.m$ is defined. Otherwise the static type of $e.m$ is \DYNAMIC{}. |
|
eernst
2015/03/26 22:38:51
Why is this commented out?
|
| +\LMHash{} |
| +The {\em closurization of getter $f$ on object $o$} is defined to be equivalent to \cd{()\{\RETURN{} u.m;\}} if $f$ is named $m$, except that iff \code{identical($o_1, o_2$)} then \cd{$o_1\#m$ == $o_2\#m$}. |
| + |
| +\LMHash{} |
| +The {\em closurization of setter $f$ on object $o$} is defined to be equivalent to \cd{(a)\{\RETURN{} u.m = a;\}} if $f$ is named $m=$, except that iff \code{identical($o_1, o_2$)} then \cd{$o_1\#m=$ == $o_2\#m=$}. |
| + |
| \commentary{ |
| There is no guarantee that \cd{identical($o_1.m, o_2.m$)}. Dart implementations are not required to canonicalize these or any other closures. |
| } |
| @@ -4078,52 +4257,114 @@ |
| The special treatment of equality in this case facilitates the use of extracted property functions in APIs where callbacks such as event listeners must often be registered and later unregistered. A common example is the DOM API in web browsers. |
| } |
| +\commentary { |
| +Observations: |
| +One cannot closurize a constructor, getter or a setter via the dot based syntax. One must use the \# based form. One can tell whether one implemented a property via a method or via a field/getter, which means that one has to plan ahead as to what construct to use, and that choice is reflected in the interface of the class. |
| +} |
| -\commentary{Observations: |
| -\begin{enumerate} |
| -\item One cannot closurize a getter or a setter. |
| -\item One can tell whether one implemented a property via a method or via a field/getter, which means that one has to plan ahead as to what construct to use, and that choice is reflected in the interface of the class. |
| -\end{enumerate} |
| -} |
| +\subsubsection{Named Constructor Closurization} |
| +\LMLabel{namedConstructorClosurization} |
| - |
| \LMHash{} |
| -The closurization of $\SUPER{}.m$ with respect to superclass $S$ is defined to be equivalent to: |
| - |
| +The {\em closurization of constructor $f$ of type $T$} is defined to be equivalent to: |
| \begin{itemize} |
| - %\item $(r_1, \ldots, r_n)\{\RETURN{}$ $o.m(r_1, \ldots, r_n);\}$ if $m$ has only required parameters $r_1, \ldots r_n$. |
| -%\item $(r_1, \ldots, r_n, rest)\{return$ $o.m(r_1, \ldots, r_n, rest);\}$ if $m$ has required parameters $r_1, \ldots r_n$, and a rest parameter $rest$. |
| -%\item |
| \item |
| \begin{dartCode} |
| -$(r_1, \ldots, r_n, \{p_1 : d_1, \ldots , p_k : d_k\})$\{ |
| - \RETURN{} \SUPER{}$.m(r_1, \ldots, r_n, p_1: p_1, \ldots, p_k: p_k)$; |
| -\} |
| +$(r_1, \ldots, r_n, \{p_1 : d_1, \ldots , p_k : d_k\})$ \{ |
| + \RETURN{} \NEW{} $T.m(r_1, \ldots, r_n, p_1: p_1, \ldots, p_k: p_k);$ |
| +\} |
| \end{dartCode} |
| -if $m$ has required parameters $r_1, \ldots, r_n$, and named parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$. |
| +if $f$ is a named constructor with name $m$ that has required parameters $r_1, \ldots, r_n$, and named parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$. |
| \item |
| \begin{dartCode} |
| $(r_1, \ldots, r_n, [p_1 = d_1, \ldots , p_k = d_k])$\{ |
| - \RETURN{} \SUPER{}$.m(r_1, \ldots, r_n, p_1, \ldots, p_k)$; |
| + \RETURN{} \NEW{} $T.m(r_1, \ldots, r_n, p_1, \ldots, p_k)$; |
| +\} |
| +\end{dartCode} |
| + |
| +if $f$ is a named constructor with name $m$ that has required parameters $r_1, \ldots, r_n$, and optional positional parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$. |
| +\end{itemize} |
| + |
| +\LMHash{} |
| +Except that iff \code{identical($T_1, T_2$)} then \cd{\NEW{} $T_1\#m$ == \NEW{} $T_2\#m$}. |
|
Lasse Reichstein Nielsen
2015/03/26 10:38:48
The identical(T_1, T_2) looks odd when you are com
gbracha
2015/03/26 23:21:21
Then I have to exclude parameterized types somehow
|
| + |
| +\commentary{ |
| +The above implies that for non-parameterized types, one can rely on the equality of closures resulting from closurization on the ``same'' type. For parameterized types, one cannot, since there is no requirement to canonicalize them. |
| +} |
| + |
| +\subsubsection{Anonymous Constructor Closurization} |
| +\LMLabel{anonymousConstructorClosurization} |
| + |
| +\LMHash{} |
| +The {\em closurization of anonymous constructor $f$ of type $T$} is defined to be equivalent to: |
| +\begin{itemize} |
| +\item |
| +\begin{dartCode} |
| +$(r_1, \ldots, r_n, \{p_1 : d_1, \ldots , p_k : d_k\})$ \{ |
| + \RETURN{} \NEW{} $T(r_1, \ldots, r_n, p_1: p_1, \ldots, p_k: p_k);$ |
| \} |
| \end{dartCode} |
| -if $m$ has required parameters $r_1, \ldots, r_n$, and optional positional parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$. |
| +if $f$ is an anonymous constructor that has required parameters $r_1, \ldots, r_n$, and named parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$. |
| +\item |
| +\begin{dartCode} |
| +$(r_1, \ldots, r_n, [p_1 = d_1, \ldots , p_k = d_k])$\{ |
| + \RETURN{} \NEW{} $T(r_1, \ldots, r_n, p_1, \ldots, p_k)$; |
| +\} |
| +\end{dartCode} |
| + |
| +if $f$ is an anonymous constructor that has required parameters $r_1, \ldots, r_n$, and optional positional parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$. |
| \end{itemize} |
| \LMHash{} |
| -Except that: |
| -\begin{enumerate} |
| -\item iff \code{identical($o_1, o_2$)} then \cd{$o_1.m$ == $o_2.m$}. |
| +Except that iff \code{identical($T_1, T_2$)} then \cd{\NEW{} $T_1\#$ == \NEW{} $T_2\#$}. |
| + |
| + |
| +\subsubsection{Super Closurization} |
| +\LMLabel{superClosurization} |
| + |
| +\LMHash{} |
| +The {\em closurization of method $f$ with respect to superclass $S$} is defined to be equivalent to: |
| + |
| +\LMHash{} |
| +\begin{itemize} |
| +\item $(a) \{\RETURN{}$ \SUPER{} $m$ $a;$\} if $f$ is named $m$ and $m$ is one of \code{$<$, $>$, $<$=, $>$=, ==, -, +, /, \~{}/, *, \%, $|$, \^{}, \&, $<<$, $>>$}. |
| +\item $() \{\RETURN{}$ \~{}\SUPER;\} if $f$ is named \~{}. |
| +\item $(a) \{\RETURN{}$ $\SUPER[a];$\} if $f$ is named $[]$. |
| +\item $(a, b) \{\RETURN{}$ $\SUPER[a] = b;$\} if $f$ is named $[]=$. |
| +\item |
| +\begin{dartCode} |
| +$(r_1, \ldots, r_n, \{p_1 : d_1, \ldots , p_k : d_k\})$ \{ |
| + \RETURN{} \SUPER$.m(r_1, \ldots, r_n, p_1: p_1, \ldots, p_k: p_k);$ |
| +\} |
| +\end{dartCode} |
| +if $f$ is named $m$ and has required parameters $r_1, \ldots, r_n$, and named parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$. |
| \item |
| -The static type of the property extraction is the static type of the method $S.m$, if $S.m$ is defined. Otherwise the static type of $\SUPER{}.m$ is \DYNAMIC{}. |
| -\end{enumerate} |
| +\begin{dartCode} |
| +$(r_1, \ldots, r_n, [p_1 = d_1, \ldots , p_k = d_k])$\{ |
| + \RETURN{} \SUPER$.m(r_1, \ldots, r_n, p_1, \ldots, p_k)$; |
| +\} |
| +\end{dartCode} |
| +if $f$ is named $m$ and has required parameters $r_1, \ldots, r_n$, and optional positional parameters $p_1, \ldots, p_k$ with defaults $d_1, \ldots, d_k$. |
| +\end{itemize} |
| +\LMHash{} |
| +Except that iff two closurizations were created by code declared in the same class with identical bindings of \THIS{} then \cd{\SUPER$_1\#m$ == \SUPER$_2\#m$}, \cd{\SUPER$_1.m$ == \SUPER$_2.m$}, \cd{\SUPER$_1\#m$ == \SUPER$_2.m$} and \cd{\SUPER$_1.m$ == \SUPER$_2\#m$}. |
| + |
| + |
| +\LMHash{} |
| +The {\em closurization of getter $f$ with respect to superclass $S$} is defined to be equivalent to \cd{()\{\RETURN{} \SUPER.m;\}} if $f$ is named $m$, except that iff two closurizations were created by code declared in the same class with identical bindings of \THIS{} then \cd{\SUPER$_1\#m$ == \SUPER$_2\#m$}. |
| + |
| +\LMHash{} |
| +The {\em closurization of setter $f$ with respect to superclass $S$} is defined to be equivalent to \cd{(a)\{\RETURN{} \SUPER.m = a;\}} if $f$ is named $m=$, except that iff two closurizations were created by code declared in the same class with identical bindings of \THIS{} then \cd{\SUPER$_1\#m=$ == \SUPER$_2\#m=$}. |
| + |
| + |
| + |
| \subsection{ Assignment} |
| \LMLabel{assignment} |
| @@ -4174,6 +4415,9 @@ |
| It is a static type warning if the static type of $e$ may not be assigned to the static type of $v$. The static type of the expression $v$ \code{=} $e$ is the static type of $e$. |
| \LMHash{} |
| +Evaluation of an assignment $a$ of the form $e_1?.v$ \code{=} $e_2$ is equivalent to the evaluation of the expression $((x) => x == \NULL? \NULL: x.v = e_2)(e_1)$. The static type of $a$ is the static type of $e_2$. |
|
eernst
2015/03/26 22:38:50
It might be an error-prone choice to let $e_2$ be
Lasse Reichstein Nielsen
2015/03/27 07:14:45
The ?? operator is definitely short-circuit: (e1 ?
eernst
2015/03/27 08:44:03
For (e1 || e2), the rationale for the short-circui
Lasse Reichstein Nielsen
2015/03/27 15:42:09
We don't actually have "v ?= e", only "o?.p = e" w
eernst
2015/04/07 10:44:49
Sorry, I meant "v ??= e".
I think the most intuit
|
| + |
| +\LMHash{} |
| Evaluation of an assignment of the form $e_1.v$ \code{=} $e_2$ proceeds as follows: |
| \LMHash{} |
| @@ -4233,10 +4477,18 @@ |
| \LMLabel{compoundAssignment} |
| \LMHash{} |
| -A compound assignment of the form $v$ $op\code{=} e$ is equivalent to $v \code{=} v$ $op$ $e$. A compound assignment of the form $C.v$ $op \code{=} e$ is equivalent to $C.v \code{=} C.v$ $op$ $e$. A compound assignment of the form $e_1.v$ $op = e_2$ is equivalent to \code{((x) $=>$ x.v = x.v $op$ $e_2$)($e_1$)} where $x$ is a variable that is not used in $e_2$. A compound assignment of the form $e_1[e_2]$ $op\code{=} e_3$ is equivalent to |
| +Evaluation of a compound assignment of the form $v$ $\code{??=} e$ is equivalent to the evaluation of the expression $((x) => x == \NULL? v=e : x)(v)$ where $x$ is a variable that is not used in $e$. Evaluation of a compound assignment of the form $C.v$ $\code{??=} e$, where $C$ is a type literal, is equivalent to the evaluation of the expression $((x) => x == \NULL? C.v=e: x)(C.v)$ where $x$ is a variable that is not used in $e$. Evaluation of a compound assignment of the form $e_1.v$ $\code{??=} e_2$ is equivalent to the evaluation of the expression $((x) =>((y) => y == \NULL? x.v = e_2: y)(x.v))(e_1)$ where $x$ and $y$ are distinct variables that are not used in $e_2$. Evaluation of a compound assignment of the form $e_1[e_2]$ $\code{??=} e_3$ is equivalent to the evaluation of the expression |
|
Paul Berry
2015/03/26 15:07:21
Nit: the pdf output of this paragraph contains som
eernst
2015/03/26 22:38:50
If null-awareness should not change the number of
eernst
2015/03/26 22:38:50
Typo?: $((x) ..)(..)$ vs. \code{((x) $=>$ ..)(..)}
gbracha
2015/03/26 23:21:22
Yes, I am aware of that. I made some changes, but
|
| +$((a, i) => ((x) => x == \NULL? a[i] = e_3: x)(a[i]))(e_1, e_2)$ where $x$, $a$ and $i$ are distinct variables that are not used in $e_3$. Evaluation of a compound assignment of the form $e_1?.v$ $\code{??=} e_2$ is equivalent to the evaluation of the expression \code{((x) $=>$ x == \NULL? \NULL: $x.v ??= e_2$)($e_1$)} where $x$ is a variable that is not used in $e_2$. |
|
Lasse Reichstein Nielsen
2015/03/26 10:38:48
Need to address super.x ??= y too?
eernst
2015/03/26 22:38:50
How about \code{$e_1$ == null}?
gbracha
2015/03/26 23:21:21
Hmm. Actually, I think we don't really cover super
gbracha
2015/03/26 23:21:22
Done.
gbracha
2015/03/26 23:21:22
How about it :-) ? Sorry not clear what you mean.
eernst
2015/03/27 08:44:03
Actually, thinking about it, no special checking i
|
| + |
| + |
| +\LMHash{} |
| +The static type of a compound assignment of the form $v$ $\code{??=} e$ or the form $C.v$ $\code{??=} e$ is the static type of $e$. The static type of a compound assignment of the form $e_1.v$ $\code{??=} e_2$ is the static type of $e_2$. The static type of a compound assignment of the form $e_1[e_2]$ $\code{??=} e_3$ is the static type of $e_3$. |
|
Paul Berry
2015/03/26 15:07:21
I don't think this is what we want. Consider the
gbracha
2015/03/26 23:21:22
Right. Likewise for all variants (v , C.v, e1.v, e
|
| + |
| +\LMHash{} |
| +For any other valid operator $op$, a compound assignment of the form $v$ $op\code{=} e$ is equivalent to $v \code{=} v$ $op$ $e$. A compound assignment of the form $C.v$ $op \code{=} e$ is equivalent to $C.v \code{=} C.v$ $op$ $e$. A compound assignment of the form $e_1.v$ $op = e_2$ is equivalent to \code{((x) $=>$ x.v = x.v $op$ $e_2$)($e_1$)} where $x$ is a variable that is not used in $e_2$. A compound assignment of the form $e_1[e_2]$ $op\code{=} e_3$ is equivalent to |
| \code{((a, i) $=>$ a[i] = a[i] $op$ $e_3$)($e_1, e_2$)} where $a$ and $i$ are a variables that are not used in $e_3$. |
| +A compound assignment of the form $e_1?.v$ $op = e_2$ is equivalent to \code{((x) $=>$ x?.v = x.v $op$ $e_2$)($e_1$)} where $x$ is a variable that is not used in $e_2$. |
|
Paul Berry
2015/03/26 15:07:21
Nit: there are some spacing errors in this paragra
|
| - |
| \begin{grammar} |
| {\bf compoundAssignmentOperator:}`*='; |
| `/='; |
| @@ -4248,7 +4500,8 @@ |
| `{\escapegrammar \gt \gt}='; |
| `\&='; |
| `\^{}='; |
| - `$|$=' |
| + `$|$='; |
| + `??='; |
| . |
| \end{grammar} |
| @@ -4261,7 +4514,7 @@ |
| \begin{grammar} |
| {\bf conditionalExpression:} |
| - logicalOrExpression (`?' expressionWithoutCascade `{\escapegrammar :}' expressionWithoutCascade)? |
| + ifNullExpression (`?' expressionWithoutCascade `{\escapegrammar :}' expressionWithoutCascade)? |
| . % the first branches could top level expressions, it seems, but certainly NOT the second |
| \end{grammar} |
| @@ -4284,7 +4537,22 @@ |
| \LMHash{} |
| It is a static type warning if the static type of $e_1$ may not be assigned to \code{bool}. The static type of $c$ is the least upper bound (\ref{leastUpperBounds}) of the static type of $e_2$ and the static type of $e_3$. |
| + |
| + |
| + \subsection{If-null Expressions} |
| + \label{ifNull} |
| + |
| + \LMHash{} |
| + An {\em if-null expression}evaluates an expression and if the result is \NULL, evaluates another. |
| + |
| +\begin{grammar} |
| +{\bf ifNullExpression:} |
| + logicalOrExpression (`??' logicalOrExpression)* |
| +\end{grammar} |
| +\LMHash{} |
| +Evaluation of an if-null expression $e$ of the form $e_1??e_2 $ is equivalent to the evaluation of the expression $((x) => x == \NULL? e_2: x)(e_1)$. The static type of $e$ is least upper bound (\ref{leastUpperBounds}) of the static type of $e_1$ and the static type of $e_2$. |
| + |
| \subsection{ Logical Boolean Expressions} |
| \LMLabel{logicalBooleanExpressions} |
| @@ -4633,7 +4901,7 @@ |
| \begin{grammar} |
| {\bf postfixExpression:}assignableExpression postfixOperator; |
| - primary selector* |
| + primary (selector* $|$ ( `\#' ( (identifier `='?) $|$ operator))) |
|
Lasse Reichstein Nielsen
2015/03/26 10:38:48
Could the #-syntax be part of selector instead?
I
gbracha
2015/03/26 23:21:21
I'm not inclined to outlaw the abuse.
|
| . |
| {\bf postfixOperator:} |
| @@ -4716,13 +4984,28 @@ |
| . |
| {\bf assignableSelector:}`[' expression `]'; % again, could be top level |
| - `{\escapegrammar .}' identifier |
| + `{\escapegrammar .}' identifier; |
| + `{\escapegrammar ?.}' identifier |
|
Lasse Reichstein Nielsen
2015/03/26 10:38:48
Different indentation?
gbracha
2015/03/26 23:21:22
Acknowledged.
|
| . |
| \end{grammar} |
| \LMHash{} |
| -An {\em assignable expression} is either: |
| +An assignable expression can be {\em conditional} or {\em unconditional}. |
| + |
| +Evaluation of a {\em conditional assignable expression} $e$ of the form $e_1?.id$ is equivalent to the evaluation of the expression $((x) => x == \NULL ? \NULL : x.id)(e_1)$. The static type of $e$ is the same as the static type of $e_1.id$. |
| + |
| +\commentary{ |
| +One might be tempted to conclude that for $e \ne \NULL{}$, $e?.v$ is always equivalent to $e.v$. However this is not the case. If $e$ is a type literal representing a type with static member $v$, the $e.v$ refers to that member, but $e?.v$ does not. |
| +} |
| + |
| +\rationale{ |
| +One could try and address this with special case rules, but this is simply a matter of digging oneself deeper into a hole. Removing the restrictions on the use of types as objects is the proper way to resolve this issue. |
|
Lasse Reichstein Nielsen
2015/03/26 10:38:48
Objection, editorializing!
gbracha
2015/03/26 23:21:22
I am the editor, after all. I wondered if anyone w
|
| +} |
| + |
| + |
| +\LMHash{} |
| +An {\em unconditional assignable expression} is either: |
| \begin{itemize} |
| \item An identifier. |
| \item An invocation of a getter (\ref{getters}) or list access operator on an expression $e$. |
| @@ -5667,7 +5950,7 @@ |
| A finally clause \FINALLY{} $s$ defines an exception handler $h$ that executes as follows: |
| \LMHash{} |
| -Let $r$ be the current return value (\ref{return}). Then the current return value becomes undefined. Any open streams associated with any asynchronous for loops (\ref{asynchronousFor-in}) and yield-each (\ref{yieldEach}) statements executing within the dynamic scope of $h$ are canceled. |
| +Let $r$ be the current return value (\ref{return}). Then the current return value becomes undefined. Any open streams associated with any asynchronous for loops (\ref{asynchronousFor-in}) and yield-each (\ref{yieldEach}) statements executing within the dynamic scope of $h$ are canceled, in the order of their nesting, innermost first. |
| \rationale{ |
| Streams left open by for loops that were escaped for whatever reason would be canceled at function termination, but it is best to cancel them as soon as possible. |
| @@ -5873,7 +6156,7 @@ |
| Let $s_b$ be a \BREAK{} statement. If $s_b$ is of the form \code{\BREAK{} $L$;}, then let $s_E$ be the the innermost labeled statement with label $L$ enclosing $s_b$. If $s_b$ is of the form \code{\BREAK{};}, then let $s_E$ be the the innermost \DO{} (\ref{do}), \FOR{} (\ref{for}), \SWITCH{} (\ref{switch}) or \WHILE{} (\ref{while}) statement enclosing $s_b$. It is a compile-time error if no such statement $s_E$ exists within the innermost function in which $s_b$ occurs. Furthermore, let $s_1, \ldots, s_n$ be those \TRY{} statements that are both enclosed in $s_E$ and that enclose $s_b$, and that have a \FINALLY{} clause. Lastly, let $f_j$ be the \FINALLY{} clause of $s_j, 1 \le j \le n$. Executing $s_b$ first executes $f_1, \ldots, f_n$ in innermost-clause-first order and then terminates $s_E$. |
| \LMHash{} |
| -If $s_E$ is an asynchronous for loop (\ref{asynchronousFor-in}), its associated stream subscription is canceled. Furthermore, let $a_k$ be the set of asynchronous for loops and yield-each statements (\ref{yieldEach}) enclosing $s_b$ that are enclosed in $s_E , 1 \le k \le m$. The stream subscriptions associated with $a_j$ are canceled, $1 \le j \le m$. |
| +If $s_E$ is an asynchronous for loop (\ref{asynchronousFor-in}), its associated stream subscription is canceled. Furthermore, let $a_k$ be the set of asynchronous for loops and yield-each statements (\ref{yieldEach}) enclosing $s_b$ that are enclosed in $s_E , 1 \le k \le m$, where $a_k$ is enclosed in $a_{k+1}$. The stream subscriptions associated with $a_j$ are canceled, $1 \le j \le m$, innermost first, so that $a_j$ is canceled before $a_{j+1}$. |
| @@ -5897,7 +6180,7 @@ |
| } |
| \LMHash{} |
| - If $s_E$ is an asynchronous for loop (\ref{asynchronousFor-in}), let $a_k$ be the set of asynchronous for loops and yield-each statements (\ref{yieldEach}) enclosing $s_c$ that are enclosed in $s_E , 1 \le k \le m$. The stream subscriptions associated with $a_j$ are canceled, $1 \le j \le m$. |
| + If $s_E$ is an asynchronous for loop (\ref{asynchronousFor-in}), let $a_k$ be the set of asynchronous for loops and yield-each statements (\ref{yieldEach}) enclosing $s_c$ that are enclosed in $s_E , 1 \le k \le m$, where $a_k$ is enclosed in $a_{k+1}$. The stream subscriptions associated with $a_j$ are canceled, $1 \le j \le m$, innermost first, so that $a_j$ is canceled before $a_{j+1}$. |
| \subsection{ Yield and Yield-Each} |
| \LMLabel{yieldAndYieldEach} |