Index: docs/language/dartLangSpec.tex |
diff --git a/docs/language/dartLangSpec.tex b/docs/language/dartLangSpec.tex |
index b0c749c63857c324dccf545ee9f625f1417d66e5..b7d7fabde60d6c719f984a35baf5954bb743fe2e 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 can be introduced by declarations of functions (\ref{functionDeclarations}), methods (\ref{instanceMethods}, \ref{staticMethods}), getters (\ref{getters}), setters (\ref{setters}), and constructors (\ref{constructors}); and they can be introduced by function literals (\ref{functionExpressions}). |
Lasse Reichstein Nielsen
2017/03/06 15:09:34
"Functions can be introduce by declarations of fun
|
\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 function declarations include a signature, and some include a body. |
Lasse Reichstein Nielsen
2017/03/06 15:09:34
Here "function declarations" looks like it only re
|
+The signature describes the formal parameter part of the function, its name, and possibly its return type, with the exceptions that a getter has no formal parameter part and a function literal has no name. |
+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/03/06 15:09:33
"formal type parameter list" - that wording rubs m
|
+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,15 @@ 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. |
+The current scope for the function's signature is the scope that encloses the formal parameter scope. |
Lasse Reichstein Nielsen
2017/03/06 15:09:34
The type parameter list is part of the signature,
|
+ |
+\commentary{ |
+This means that in a generic function, the return type and parameter type annotations can use the formal type parameters, but the formal parameters are not in scope in the signature. |
+} |
\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 +790,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 +849,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 +2312,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 +2326,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 +2436,68 @@ 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{} |
+Some function declarations may include a {\em formal type parameter list} (\ref{functions}), in which case we say that it is a {\em generic function}. |
+A {\em non-generic function} is a function which is not generic. |
+ |
+\commentary{ |
+The following exceptions exist: |
+Getter, setter, operator, and constructor declarations cannot be generic. |
+} |
+ |
+\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. |
+ |
+\commentary{ |
+This enables the use of F-bounded type parameters. |
+Moreover, 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{} |
+{ \def\Derased{\ensuremath{D_{\mbox{\scriptsize erased}}}} |
+{\em Generic function erasure} takes as input a generic function declaration $D$ and either yields a non-generic function declaration \Derased{} or terminates with a compile-time error. |
+\Derased{} is identical to $D$ except for the following replacements: |
+\begin{itemize} |
+\item The \GrammarSymbol{formalParameterPart} of \Derased{} is identical to the \GrammarSymbol{formalParameterList} of $D$. |
+ \commentary{That is, the type parameter list is erased.} |
+\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. |
Lasse Reichstein Nielsen
2017/03/06 15:09:34
Should we include `on` clauses?
Lasse Reichstein Nielsen
2017/03/06 15:09:34
I'm actually not sure what a "type literal" really
|
+ \item In all other cases, the location corresponding to $id$ in \Derased{} contains \DYNAMIC{}. |
+ \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. |
Lasse Reichstein Nielsen
2017/03/06 15:09:33
and in things like `x is Foo<T>`, which is neither
|
+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{}. |
Lasse Reichstein Nielsen
2017/03/06 15:09:33
The "finally" here sounds like it's a separate thi
|
+} |
\section{Metadata} |
\LMLabel{metadata} |
@@ -3231,7 +3321,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 +3330,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 +3770,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. |
Lasse Reichstein Nielsen
2017/03/06 15:09:33
That sounds like you actually pass something. As I
|
+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 +3804,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 +3876,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 expression is always parsed as a generic function invocation. |
Lasse Reichstein Nielsen
2017/03/06 15:09:33
The ambiguity is not just in argument lists, it's
|
+ |
+% 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. |
Lasse Reichstein Nielsen
2017/03/06 15:09:34
We should specify which programs are valid, and wh
|
+ |
+\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/03/06 15:09:33
Nitpick: You don't know the type is `bool`, operat
|
+Note that the ambiguity may be eliminated by omitting the parentheses around the expression $d$, or adding parentheses around one of the relational expressions. |
+} |
+ |
+\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 +4199,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 +5236,7 @@ Postfix expressions invoke the postfix operators on objects. |
. |
{\bf selector:}assignableSelector; |
- arguments |
+ argumentPart |
. |
{\bf incrementOperator:}`++'; |
@@ -5296,20 +5416,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} |