Index: docs/language/dartLangSpec.tex |
diff --git a/docs/language/dartLangSpec.tex b/docs/language/dartLangSpec.tex |
index b0c749c63857c324dccf545ee9f625f1417d66e5..57a2a9d99f83b23d49ffbf9eada66e3a68189299 100644 |
--- a/docs/language/dartLangSpec.tex |
+++ b/docs/language/dartLangSpec.tex |
@@ -594,7 +594,11 @@ Functions abstract over executable actions. |
\begin{grammar} |
{\bf functionSignature:} |
- metadata returnType? identifier formalParameterList |
+ metadata returnType? identifier formalParameterPart |
+ . |
+ |
+{\bf formalParameterPart:} |
+ typeParameters? formalParameterList |
. |
{\bf returnType:} |
@@ -613,10 +617,14 @@ Functions abstract over executable actions. |
\end{grammar} |
\LMHash{} |
-Functions include function declarations (\ref{functionDeclarations}), methods (\ref{instanceMethods}, \ref{staticMethods}), getters (\ref{getters}), setters (\ref{setters}), constructors (\ref{constructors}) and function literals (\ref{functionExpressions}). |
+Functions include function declarations (\ref{functionDeclarations}), methods (\ref{instanceMethods}, \ref{staticMethods}), getters (\ref{getters}), setters (\ref{setters}), constructors (\ref{constructors}) and function literals (\ref{functionExpressions}). |
Lasse Reichstein Nielsen
2017/02/13 10:26:31
Does "function" refer to the syntactic declaration
eernst
2017/02/14 11:26:44
This is one of several cases where I've removed sp
|
\LMHash{} |
-All functions have a signature and a body. The signature describes the formal parameters of the function, and possibly its name and return type. A function body is either: |
+All functions have a signature and a body. |
Lasse Reichstein Nielsen
2017/02/13 10:26:32
... except abstract and external methods have no b
eernst
2017/02/14 11:26:44
Maintaining the focus on syntax, and allowing for
|
+The signature describes the formal parameter part of the function, its name, and possibly its return type. |
Lasse Reichstein Nielsen
2017/02/13 10:26:31
... except that function expressions do not have a
eernst
2017/02/14 11:26:44
Adjusted to mention the exceptions (getter, litera
|
+The formal parameter part optionally specifies the formal type parameter list of the function, and it specifies its formal parameter list. |
Lasse Reichstein Nielsen
2017/02/13 10:26:32
formal parameter list, if any.
(Getters have no f
eernst
2017/02/14 11:26:44
I've mentioned the exception for getters above, so
|
+The effect of a declaration $D$ of a function that includes a formal type parameter list is the same as the effect of the declaration obtained by the generic function erasure of $D$ (\ref{genericFunctionErasure}). |
+A function body is either: |
\begin{itemize} |
\item A block statement (\ref{blocks}) containing the statements (\ref{statements}) executed by the function, optionally marked with one of the modifiers: \ASYNC, \ASYNC* or \SYNC*. In this case, if the last statement of a function is not a return statement (\ref{return}), the statement \code{\RETURN{};} is implicitly appended to the function body. |
@@ -697,7 +705,11 @@ When we say that a function $f_1$ {\em forwards} to another function $f_2$, we m |
Every function includes a {\em formal parameter list}, which consists of a list of required positional parameters (\ref{requiredFormals}), followed by any optional parameters (\ref{optionalFormals}). The optional parameters may be specified either as a set of named parameters or as a list of positional parameters, but not both. |
\LMHash{} |
-The formal parameter list of a function introduces a new scope known as the function's {\em formal parameter scope}. The formal parameter scope of a function $f$ is enclosed in the scope where $f$ is declared. Every formal parameter introduces a local variable into the formal parameter scope. However, the scope of a function's signature is the function's enclosing scope, not the formal parameter scope. |
+The formal parameter list of a function introduces a new scope known as the function's {\em formal parameter scope}. |
+The formal parameter scope of a non-generic function $f$ is enclosed in the scope where $f$ is declared. |
+The formal parameter scope of a generic function $f$ is enclosed in the formal type parameter scope of $f$ (\ref{genericFunctionErasure}). |
+Every formal parameter introduces a local variable into the formal parameter scope. |
+However, the scope of a function's signature is the function's enclosing scope, not the formal parameter scope. |
Lasse Reichstein Nielsen
2017/02/13 10:26:32
What *is* a "signature"?
eernst
2017/02/14 11:26:44
Line 712 is again something that I did not touch (
|
\LMHash{} |
The body of a function introduces a new scope known as the function's {\em body scope}. The body scope of a function $f$ is enclosed in the scope introduced by the formal parameter scope of $f$. |
@@ -774,8 +786,8 @@ A {\em required formal parameter} may be specified in one of three ways: |
. |
{\bf fieldFormalParameter:} |
- metadata finalConstVarOrType? \THIS{} `{\escapegrammar .}' identifier formalParameterList? |
- . |
+ metadata finalConstVarOrType? \THIS{} `{\escapegrammar .}' identifier formalParameterPart? |
+ . |
\end{grammar} |
%\subsubsection{Rest Formals} |
@@ -833,6 +845,14 @@ If we allowed named parameters to begin with an underscore, they would be consid |
If a function does not declare a return type explicitly, its return type is \DYNAMIC{} (\ref{typeDynamic}), unless it is a constructor function, in which case its return type is the immediately enclosing class. |
\LMHash{} |
+A function may declare formal type parameters. |
+The type of the function is the type of the corresponding function obtained by generic function erasure (\ref{genericFunctionErasure}). |
+ |
+\commentary{ |
+Hence, formal type parameters are not mentioned in the following, but they are allowed to exist. |
+} |
+ |
+\LMHash{} |
Let $F$ be a function with required formal parameters $T_1$ $p_1 \ldots, T_n$ $p_n$, return type $T_0$ and no optional parameters. Then the type of $F$ is $(T_1 ,\ldots, T_n) \rightarrow T_0$. |
\LMHash{} |
@@ -2288,8 +2308,9 @@ It is also a compile-time error to subclass, mix-in or implement an enum or to e |
\LMLabel{generics} |
\LMHash{} |
-A class declaration (\ref{classes}) or type alias (\ref{typedef}) |
-$G$ may be {\em generic}, that is, $G$ may have formal type parameters declared. A generic declaration induces a family of declarations, one for each set of actual type parameters provided in the program. |
+A class declaration (\ref{classes}), type alias (\ref{typedef}), or function (\ref{functions}) $G$ may be {\em generic}, that is, $G$ may have formal type parameters declared. |
+A declaration of a generic class or a generic type alias induces a family of declarations, one for each actual type argument list provided in the program. |
+The effect of a declaration $D$ of a generic function is the same as the effect of the declaration obtained by generic function erasure of $D$ (\ref{genericFunctionErasure}). |
\begin{grammar} |
{\bf typeParameter:} |
@@ -2301,7 +2322,10 @@ $G$ may be {\em generic}, that is, $G$ may have formal type parameters declared. |
\end{grammar} |
\LMHash{} |
-A type parameter $T$ may be suffixed with an \EXTENDS{} clause that specifies the {\em upper bound} for $T$. If no \EXTENDS{} clause is present, the upper bound is \code{Object}. It is a static type warning if a type parameter is a supertype of its upper bound. The bounds of type variables are a form of type annotation and have no effect on execution in production mode. |
+A type parameter $T$ may be suffixed with an \EXTENDS{} clause that specifies the {\em upper bound} for $T$. |
+If no \EXTENDS{} clause is present, the upper bound is \code{Object}. |
+It is a static type warning if an actual type argument to a class or a type alias is not a subtype of its upper bound. |
+The bounds of type variables are a form of type annotation and have no effect on execution in production mode. |
\LMHash{} |
Type parameters are declared in the type-parameter scope of a class. |
@@ -2408,6 +2432,65 @@ The normative versions of these are given in the appropriate sections of this s |
%It is a compile-time error if a type $T$ appears more than once in the implements or eextends clause of an interface injection. |
+\subsection{Generic Function Erasure} |
+\LMLabel{genericFunctionErasure} |
+ |
+\commentary{ |
+Generic functions will be fully supported in a future version of the language. |
+The current level of support allows programs using generic functions to be written, compiled, and executed. |
+The type checks and dynamic semantics essentially erase the formal type parameters and actual type arguments. |
+With some extra care, the same source code can be used both in this language and in a version of the language with full support for generic functions. |
+Type checking with full support for generic functions may then ensure some consistency properties which remain valid also in this context. |
+This section explains how generic function erasure works. |
+} |
+ |
+\LMHash{} |
+Many function declarations may include a {\em formal type parameter list} (\ref{functions}), in which case we say that it is a {\em generic function}. |
Lasse Reichstein Nielsen
2017/02/13 10:26:31
"Many" -> "Some".
eernst
2017/02/14 11:26:44
Done.
|
+A {\em non-generic function} is a function which is not generic. |
+ |
+\commentary{ |
+The exceptions are getter, setter, operator, and constructor declarations. |
Lasse Reichstein Nielsen
2017/02/13 10:26:31
"... , which cannot be generic."
(Didn't say what
eernst
2017/02/14 11:26:44
Done.
|
+} |
+ |
+\LMHash{} |
+The formal type parameter list of a function introduces a new scope known as the function's {\em formal type parameter scope}. |
+The formal type parameter scope of a generic function $f$ is enclosed in the scope where $f$ is declared. |
+Every formal type parameter introduces a type into the formal type parameter scope. |
+ |
+\LMHash{} |
+The formal type parameter scope of a function $f$ is the current scope for the return type of $f$, if any, and for the formal type parameter list itself. |
Lasse Reichstein Nielsen
2017/02/13 10:26:31
The type parameter list is in its own scope. What
eernst
2017/02/14 11:26:44
The declaring occurrence of a type parameter ident
|
+ |
+\commentary{ |
+This enables the use of F-bounded type parameters (if you don't know what that is, see~\ref{generics}). |
Lasse Reichstein Nielsen
2017/02/13 10:26:32
Drop this enitre sentence. It doesn't say anything
eernst
2017/02/14 11:26:44
It was a stupid joke (referring to \ref{generics}:
|
+The formal type parameter scope is the enclosing scope for the formal parameter scope (\ref{formalParameters}), which enables usage of the type parameters in type annotations in the parameter list, and in the body of the function. |
+} |
+ |
+\LMHash{} |
+{\em Generic function erasure} takes as input a generic function declaration $D$ and either yields a non-generic function declaration $D^{\prime}$ or terminates with a compile-time error. |
Lasse Reichstein Nielsen
2017/02/13 10:26:32
Do you need to super-script the \prime?
Consider u
eernst
2017/02/14 11:26:44
As far as I can see, we have 54 occurrences of `\p
|
+$D^{\prime}$ is identical to $D$ except for the following replacements: |
+\begin{itemize} |
+\item The formalParameterPart of $D^{\prime}$ is identical to the formalParameterList of $D$. |
Lasse Reichstein Nielsen
2017/02/13 10:26:32
Should "formalParameterPart" be styled in some way
eernst
2017/02/14 11:26:44
The grammar rules in text actually do not have any
|
+ \commentary{That is, the type parameter list is erased.} |
Lasse Reichstein Nielsen
2017/02/13 10:26:32
erased -> omitted
"erase" is a destructive operat
eernst
2017/02/14 11:26:44
True. I actually wrote `omitted` first because tha
|
+\item Each occurrence in $D$ of an identifier $id$ which denotes a formal type parameter is processed as follows: |
+ \begin{itemize} |
+ \item If $id$ occurs as \code{$e$ \IS{} $id$} or \code{$e$ \IS{}! $id$} for some expression $e$, or if $id$ occurs as a type literal, a compile-time error occurs. |
+ \item In all other cases, the location corresponding to $id$ in $D^{\prime}$ contains \DYNAMIC{}. |
Lasse Reichstein Nielsen
2017/02/13 10:26:31
... all other cases, the occurrence of $id$ in $D$
eernst
2017/02/14 11:26:44
Frem og tilbage er lige langt. ;-D
In this case,
|
+ \end{itemize} |
+\end{itemize} |
+ |
+\commentary{ |
+This means that formal type parameters in a generic function work like \DYNAMIC{} when used as type annotations. |
+This is also the case when they are used as type arguments, both in type annotations and in instance creation expressions. |
+For example, \code{\RETURN{} <T>[];} will return a \code{List<\DYNAMIC{}>}. |
+Finally, \code{$e$ \AS{} $id$} will work like \code{$e$ \AS{} \DYNAMIC{}}, i.e., the dynamic check associated with a cast is omitted, and the static type of the expression will be \DYMAMIC{}. |
+} |
+ |
+\rationale{ |
+The check associated with a cast to a type parameter of a generic function is omitted because such checks are almost always expected to succeed. |
+This may introduce bugs in failure handling, so a more defensive style of programming may be needed around such casts. |
+In contrast, an is-expression may yield \TRUE{} as well as \FALSE{} during normal processing, and it could silently introduce bugs into correct programs if we had chosen to always evaluate these is-expressions to a fixed value like \TRUE{}. |
+Finally, it could silently introduce bugs into correct programs if we had chosen to let type literals evaluate to a fixed value, e.g., \DYNAMIC{}. |
+} |
\section{Metadata} |
\LMLabel{metadata} |
@@ -3231,7 +3314,7 @@ A {\em function literal} is an object that encapsulates an executable unit of co |
\begin{grammar} |
{\bf functionExpression:} |
- formalParameterList functionBody |
+ formalParameterPart functionBody |
. |
\end{grammar} |
@@ -3240,7 +3323,6 @@ The class of a function literal implements the built-in class \code{Function}. |
%Invoking the getter \code{runtimeType} on a function literal returns the \code{Type} object that is the value of the expression \code{Function}. |
% not necessarily |
- |
%Q{Can anyone implement it? Then we should define things via call} |
\LMHash{} |
@@ -3681,7 +3763,11 @@ As discussed in section \ref{errorsAndWarnings}, the handling of a suspended iso |
\LMLabel{functionInvocation} |
\LMHash{} |
-Function invocation occurs in the following cases: when a function expression (\ref{functionExpressions}) is invoked (\ref{functionExpressionInvocation}), when a method (\ref{methodInvocation}), getter (\ref{topLevelGetterInvocation}, \ref{propertyExtraction}) or setter (\ref{assignment}) is invoked or when a constructor is invoked (either via instance creation (\ref{instanceCreation}), constructor redirection (\ref{redirectingConstructors}) or super initialization). The various kinds of function invocation differ as to how the function to be invoked, $f$, is determined, as well as whether \THIS{} (\ref{this}) is bound. Once $f$ has been determined, the formal parameters of $f$ are bound to corresponding actual arguments. When the body of $f$ is executed it will be executed with the aforementioned bindings. |
+Function invocation occurs in the following cases: when a function expression (\ref{functionExpressions}) is invoked (\ref{functionExpressionInvocation}), when a method (\ref{methodInvocation}), getter (\ref{topLevelGetterInvocation}, \ref{propertyExtraction}) or setter (\ref{assignment}) is invoked or when a constructor is invoked (either via instance creation (\ref{instanceCreation}), constructor redirection (\ref{redirectingConstructors}) or super initialization). |
+The various kinds of function invocation differ as to how the function to be invoked, $f$, is determined, as well as whether \THIS{} (\ref{this}) is bound. |
+Once $f$ has been determined, the formal parameters of $f$ are bound to corresponding actual arguments. |
+The actual type arguments passed to $f$, if any, have no effect. |
+When the body of $f$ is executed it will be executed with the aforementioned bindings. |
\LMHash{} |
If $f$ is synchronous and is not a generator (\ref{functions}) then execution of the body of $f$ begins immediately. |
@@ -3711,7 +3797,7 @@ The contract explicitly mentions a number of situations where certain iterables |
} |
\LMHash{} |
-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 execution of the body of $f$ completes (\ref{completion}, |
+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 execution of the body of $f$ completes (\ref{completion}), |
\begin{itemize} |
\item If it returns without a value or it completes normally (\ref{completion}), $j$ is positioned after its last element, so that its current value is \code{null} and the current call to \code{moveNext()} on $j$ returns false, as must all further calls. |
\item If it throws an 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. |
@@ -3783,7 +3869,30 @@ Function invocation involves evaluation of the list of actual arguments to the f |
. |
\end{grammar} |
-Argument lists allow an optional trailing comma after the last argument ($`,'?$). An argument list with such a trailing comma is equivalent in all ways to the same parameter list without the trailing comma. All argument lists in this specification are shown without a trailing comma, but the rules and semantics apply equally to the corresponding argument list with a trailing comma. |
+\LMHash{} |
+Argument lists allow an optional trailing comma after the last argument ($`,'?$). |
+An argument list with such a trailing comma is equivalent in all ways to the same argument list without the trailing comma. |
+All argument lists in this specification are shown without a trailing comma, but the rules and semantics apply equally to the corresponding argument list with a trailing comma. |
+ |
+\LMHash{} |
+When parsing an argument list, an ambiguity may arise because the same source code could be one generic function invocation, and it could be two or more relational expressions and/or shift expressions. |
+In this situation, the parse as a generic function invocation is chosen. |
Lasse Reichstein Nielsen
2017/02/13 10:26:32
-> In this situation, the expression is always par
eernst
2017/02/14 11:26:44
Done.
|
+ |
+% Should we specify the precise disambiguation rule here?: |
+% We have seen 'a', '<', a matching '>', and '(', where |
+% 'a' is tricky because we can have things like 'new Foo().m<...>(...', |
+% 'x..y(...).m<...>(...', etc, basically everything that can precede |
+% argumentPart in the grammar. |
+ |
+\commentary{ |
+An example is \code{f(a<B, C>($d$))}, which may be an invocation of \code{f} passing two actual arguments of type \code{bool}, or an invocation of \code{f} passing the result returned by an invocation of the generic function \code{a}. |
Lasse Reichstein Nielsen
2017/02/13 10:26:32
Why is $d$ in code, but not a, B or C?
I can see t
eernst
2017/02/14 11:26:44
Right, but this is commentary and we just need a s
|
+Note that the ambiguity may be eliminated by omitting the parentheses around the expression $d$, or adding parentheses around one of the relational expressions. |
Lasse Reichstein Nielsen
2017/02/13 10:26:31
Or around \code{B} or \code{C}.
eernst
2017/02/14 11:26:44
That wouldn't actually work, because we did not re
|
+} |
+ |
+\rationale{ |
+When the intention is to pass several relational or shift expressions as actual arguments and there is an ambiguity, the source code can easily be adjusted to a form which is unambiguous. |
+Also, we expect that it will be more common to have generic function invocations as actual arguments than having relational or shift expressions that happen to match up and have parentheses at the end, such that the ambiguity arises. |
+} |
\LMHash{} |
Evaluation of an actual argument list of the form |
@@ -4083,12 +4192,16 @@ where $e$ is an expression and \metavar{suffix} is a sequence of operator, metho |
\begin{grammar} |
{\bf cascadeSection:} |
- `{\escapegrammar ..}' (cascadeSelector arguments*) (assignableSelector arguments*)* (assignmentOperator expressionWithoutCascade)? |
- . |
+ `{\escapegrammar ..}' (cascadeSelector argumentPart*) (assignableSelector argumentPart*)* (assignmentOperator expressionWithoutCascade)? |
+ . |
-{\bf cascadeSelector:}`[' expression `]'; |
+{\bf cascadeSelector:}`[' expression `]'; |
identifier |
- . |
+ . |
+ |
+{\bf argumentPart:} |
+ typeArguments? arguments |
+ . |
\end{grammar} |
\LMHash{} |
@@ -5116,7 +5229,7 @@ Postfix expressions invoke the postfix operators on objects. |
. |
{\bf selector:}assignableSelector; |
- arguments |
+ argumentPart |
. |
{\bf incrementOperator:}`++'; |
@@ -5296,20 +5409,19 @@ Of course, if assignable expressions always appeared {\em as} the left hand side |
\begin{grammar} |
-{\bf assignableExpression:}primary (arguments* assignableSelector)+; |
+{\bf assignableExpression:}primary (argumentPart* assignableSelector)+; |
\SUPER{} unconditionalAssignableSelector; |
identifier |
. |
{\bf unconditionalAssignableSelector:}`[' expression `]'; % again, could be top level |
- `{\escapegrammar .}' identifier |
+ `{\escapegrammar .}' identifier |
. |
{\bf assignableSelector:} |
- unconditionalAssignableSelector; |
- `{\escapegrammar ?.}' identifier |
+ unconditionalAssignableSelector; |
+ `{\escapegrammar ?.}' identifier |
. |
- |
\end{grammar} |