Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: docs/language/dartLangSpec.tex

Issue 2690553002: Added generic method syntax to language specification.
Patch Set: Review response Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 \documentclass{article} 1 \documentclass{article}
2 \usepackage{epsfig} 2 \usepackage{epsfig}
3 \usepackage{color} 3 \usepackage{color}
4 \usepackage{dart} 4 \usepackage{dart}
5 \usepackage{bnf} 5 \usepackage{bnf}
6 \usepackage{hyperref} 6 \usepackage{hyperref}
7 \usepackage{lmodern} 7 \usepackage{lmodern}
8 \usepackage[T1]{fontenc} 8 \usepackage[T1]{fontenc}
9 \newcommand{\code}[1]{{\sf #1}} 9 \newcommand{\code}[1]{{\sf #1}}
10 \title{Dart Programming Language Specification \\ 10 \title{Dart Programming Language Specification \\
(...skipping 576 matching lines...) Expand 10 before | Expand all | Expand 10 after
587 587
588 588
589 \section{Functions} 589 \section{Functions}
590 \LMLabel{functions} 590 \LMLabel{functions}
591 591
592 \LMHash{} 592 \LMHash{}
593 Functions abstract over executable actions. 593 Functions abstract over executable actions.
594 594
595 \begin{grammar} 595 \begin{grammar}
596 {\bf functionSignature:} 596 {\bf functionSignature:}
597 metadata returnType? identifier formalParameterList 597 metadata returnType? identifier formalParameterPart
598 .
599
600 {\bf formalParameterPart:}
601 typeParameters? formalParameterList
598 . 602 .
599 603
600 {\bf returnType:} 604 {\bf returnType:}
601 \VOID{}; 605 \VOID{};
602 type 606 type
603 . 607 .
604 608
605 {\bf functionBody:} \ASYNC{}? `={\escapegrammar \gt}' expression `{\escapegramm ar ;}'; 609 {\bf functionBody:} \ASYNC{}? `={\escapegrammar \gt}' expression `{\escapegramm ar ;}';
606 (\ASYNC{} $|$ \ASYNC* $|$ \SYNC*)? block 610 (\ASYNC{} $|$ \ASYNC* $|$ \SYNC*)? block
607 . 611 .
608 612
609 {\bf block:} 613 {\bf block:}
610 `\{' statements `\}' 614 `\{' statements `\}'
611 . 615 .
612 616
613 \end{grammar} 617 \end{grammar}
614 618
615 \LMHash{} 619 \LMHash{}
616 Functions include function declarations (\ref{functionDeclarations}), methods ( \ref{instanceMethods}, \ref{staticMethods}), getters (\ref{getters}), setters (\ref{setters}), constructors (\ref{constructors}) and function literals (\re f{functionExpressions}). 620 Functions can be introduced by declarations of functions (\ref{functionDeclarati ons}), methods (\ref{instanceMethods}, \ref{staticMethods}), getters (\ref{gette rs}), setters (\ref{setters}), and constructors (\ref{constructors}); and they c an be introduced by function literals (\ref{functionExpressions}).
Lasse Reichstein Nielsen 2017/03/06 15:09:34 "Functions can be introduce by declarations of fun
617 621
618 \LMHash{} 622 \LMHash{}
619 All functions have a signature and a body. The signature describes the formal pa rameters of the function, and possibly its name and return type. A function bod y is either: 623 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
624 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 param eter part and a function literal has no name.
625 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
626 The effect of a declaration $D$ of a function that includes a formal type parame ter list is the same as the effect of the declaration obtained by the generic fu nction erasure of $D$ (\ref{genericFunctionErasure}).
627 A function body is either:
620 \begin{itemize} 628 \begin{itemize}
621 \item A block statement (\ref{blocks}) containing the statements (\ref{stateme nts}) executed by the function, optionally marked with one of the modifiers: \AS YNC, \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 implicitl y appended to the function body. 629 \item A block statement (\ref{blocks}) containing the statements (\ref{stateme nts}) executed by the function, optionally marked with one of the modifiers: \AS YNC, \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 implicitl y appended to the function body.
622 630
623 \rationale{ 631 \rationale{
624 Because Dart is optionally typed, we cannot guarantee that a function that does not return a value will not be used in the context of an expression. Therefore, every function must return a value. A \RETURN{} without an expression returns \N ULL{}. For generator functions, the situation is more subtle. See further discus sion in section \ref{return}. 632 Because Dart is optionally typed, we cannot guarantee that a function that does not return a value will not be used in the context of an expression. Therefore, every function must return a value. A \RETURN{} without an expression returns \N ULL{}. For generator functions, the situation is more subtle. See further discus sion in section \ref{return}.
625 } 633 }
626 634
627 OR 635 OR
628 \item of the form \code{=> $e$} which is equivalent to a body of the form \cod e{\{\RETURN{} $e$;\}} or the form \code{\ASYNC{} => $e$} which is equivalent to a body of the form \code{\ASYNC{} \{\RETURN{} $e$;\}}. \rationale{The other modi fiers do not apply here, because they apply only to generators, discussed below, and generators do not allow the form \code{\RETURN{} $e$}; values are added to the generated stream or iterable using \YIELD{} instead.} 636 \item of the form \code{=> $e$} which is equivalent to a body of the form \cod e{\{\RETURN{} $e$;\}} or the form \code{\ASYNC{} => $e$} which is equivalent to a body of the form \code{\ASYNC{} \{\RETURN{} $e$;\}}. \rationale{The other modi fiers do not apply here, because they apply only to generators, discussed below, and generators do not allow the form \code{\RETURN{} $e$}; values are added to the generated stream or iterable using \YIELD{} instead.}
629 637
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
690 When we say that a function $f_1$ {\em forwards} to another function $f_2$, we m ean that invoking $f_1$ causes $f_2$ to be executed with the same arguments an d/or receiver as $f_1$, and returns the result of executing $f_2$ to the caller of $f_1$, unless $f_2$ throws an exception, in which case $f_1$ throws the same exception. Furthermore, we only use the term for synthetic functions introduced by the specification. 698 When we say that a function $f_1$ {\em forwards} to another function $f_2$, we m ean that invoking $f_1$ causes $f_2$ to be executed with the same arguments an d/or receiver as $f_1$, and returns the result of executing $f_2$ to the caller of $f_1$, unless $f_2$ throws an exception, in which case $f_1$ throws the same exception. Furthermore, we only use the term for synthetic functions introduced by the specification.
691 699
692 700
693 \subsection{Formal Parameters} 701 \subsection{Formal Parameters}
694 \LMLabel{formalParameters} 702 \LMLabel{formalParameters}
695 703
696 \LMHash{} 704 \LMHash{}
697 Every function includes a {\em formal parameter list}, which consists of a list of required positional parameters (\ref{requiredFormals}), followed by any optio nal 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. 705 Every function includes a {\em formal parameter list}, which consists of a list of required positional parameters (\ref{requiredFormals}), followed by any optio nal 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.
698 706
699 \LMHash{} 707 \LMHash{}
700 The formal parameter list of a function introduces a new scope known as the func tion'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 intr oduces 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 paramete r scope. 708 The formal parameter list of a function introduces a new scope known as the func tion's {\em formal parameter scope}.
709 The formal parameter scope of a non-generic function $f$ is enclosed in the scop e where $f$ is declared.
710 The formal parameter scope of a generic function $f$ is enclosed in the formal t ype parameter scope of $f$ (\ref{genericFunctionErasure}).
711 Every formal parameter introduces a local variable into the formal parameter sco pe.
712 The current scope for the function's signature is the scope that encloses the fo rmal parameter scope.
Lasse Reichstein Nielsen 2017/03/06 15:09:34 The type parameter list is part of the signature,
713
714 \commentary{
715 This means that in a generic function, the return type and parameter type annota tions can use the formal type parameters, but the formal parameters are not in s cope in the signature.
716 }
701 717
702 \LMHash{} 718 \LMHash{}
703 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$. 719 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$.
704 720
705 721
706 %The formal parameter scope of a function maps the name of each formal parameter $p$ to the value $p$ is bound to. 722 %The formal parameter scope of a function maps the name of each formal parameter $p$ to the value $p$ is bound to.
707 723
708 % The formal parameters of a function are processed in the enclosing scope of th e function. 724 % The formal parameters of a function are processed in the enclosing scope of th e function.
709 % \commentary{this means that the parameters themselves may not be referenced wi thin the formal parameter list.} 725 % \commentary{this means that the parameters themselves may not be referenced wi thin the formal parameter list.}
710 726
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
767 {\bf normalFormalParameter:}functionSignature; 783 {\bf normalFormalParameter:}functionSignature;
768 fieldFormalParameter; 784 fieldFormalParameter;
769 simpleFormalParameter 785 simpleFormalParameter
770 . 786 .
771 787
772 {\bf simpleFormalParameter:}declaredIdentifier; 788 {\bf simpleFormalParameter:}declaredIdentifier;
773 metadata identifier 789 metadata identifier
774 . 790 .
775 791
776 {\bf fieldFormalParameter:} 792 {\bf fieldFormalParameter:}
777 metadata finalConstVarOrType? \THIS{} `{\escapegrammar .}' identifier formalP arameterList? 793 metadata finalConstVarOrType? \THIS{} `{\escapegrammar .}' identifier form alParameterPart?
778 . 794 .
779 \end{grammar} 795 \end{grammar}
780 796
781 %\subsubsection{Rest Formals} 797 %\subsubsection{Rest Formals}
782 %\LMLabel{restFormals} 798 %\LMLabel{restFormals}
783 799
784 %A rest formal $R$ must be the last parameter in a formal parameter list. If a type $T$ is specified for $R$, it signifies that the type of $R$ is $T[]$. 800 %A rest formal $R$ must be the last parameter in a formal parameter list. If a type $T$ is specified for $R$, it signifies that the type of $R$ is $T[]$.
785 801
786 %\begin{grammar} 802 %\begin{grammar}
787 %restFormalParameter: 803 %restFormalParameter:
788 % finalConstVarOrType? '{\escapegrammar ...}' identifier 804 % finalConstVarOrType? '{\escapegrammar ...}' identifier
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
826 If we allowed named parameters to begin with an underscore, they would be consid ered private and inaccessible to callers from outside the library where it was d efined. If a method outside the library overrode a method with a private optiona l name, it would not be a subtype of the original method. The static checker wou ld of course flag such situations, but the consequence would be that adding a pr ivate named formal would break clients outside the library in a way they could n ot easily correct. 842 If we allowed named parameters to begin with an underscore, they would be consid ered private and inaccessible to callers from outside the library where it was d efined. If a method outside the library overrode a method with a private optiona l name, it would not be a subtype of the original method. The static checker wou ld of course flag such situations, but the consequence would be that adding a pr ivate named formal would break clients outside the library in a way they could n ot easily correct.
827 } 843 }
828 844
829 \subsection{Type of a Function} 845 \subsection{Type of a Function}
830 \LMLabel{typeOfAFunction} 846 \LMLabel{typeOfAFunction}
831 847
832 \LMHash{} 848 \LMHash{}
833 If a function does not declare a return type explicitly, its return type is \DYN AMIC{} (\ref{typeDynamic}), unless it is a constructor function, in which case i ts return type is the immediately enclosing class. 849 If a function does not declare a return type explicitly, its return type is \DYN AMIC{} (\ref{typeDynamic}), unless it is a constructor function, in which case i ts return type is the immediately enclosing class.
834 850
835 \LMHash{} 851 \LMHash{}
852 A function may declare formal type parameters.
853 The type of the function is the type of the corresponding function obtained by g eneric function erasure (\ref{genericFunctionErasure}).
854
855 \commentary{
856 Hence, formal type parameters are not mentioned in the following, but they are a llowed to exist.
857 }
858
859 \LMHash{}
836 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$. 860 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$.
837 861
838 \LMHash{} 862 \LMHash{}
839 Let $F$ be a function with required formal parameters $T_1$ $p_1 \ldots, T_n$ $p _n$, return type $T_0$ and positional optional parameters $T_{n+1}$ $p_{n+1}, \l dots, T_{n+k}$ $ p_{n+k}$. Then the type of $F$ is $(T_1 ,\ldots, T_n, [T_{n+1}$ $p_{n+1}, \ldots, T_{n+k}$ $p_{n+k}]) \rightarrow T_0$. 863 Let $F$ be a function with required formal parameters $T_1$ $p_1 \ldots, T_n$ $p _n$, return type $T_0$ and positional optional parameters $T_{n+1}$ $p_{n+1}, \l dots, T_{n+k}$ $ p_{n+k}$. Then the type of $F$ is $(T_1 ,\ldots, T_n, [T_{n+1}$ $p_{n+1}, \ldots, T_{n+k}$ $p_{n+k}]) \rightarrow T_0$.
840 864
841 \LMHash{} 865 \LMHash{}
842 Let $F$ be a function with required formal parameters $T_1$ $p_1 \ldots, T_n$ $p _n$, return type $T_0$ and named optional parameters $T_{n+1}$ $p_{n+1}, \ldots, T_{n+k}$ $ p_{n+k}$. Then the type of $F$ is $(T_1 ,\ldots, T_n, \{T_{n+1}$ $p_ {n+1}, \ldots, T_{n+k}$ $p_{n+k}\}) \rightarrow T_0$. 866 Let $F$ be a function with required formal parameters $T_1$ $p_1 \ldots, T_n$ $p _n$, return type $T_0$ and named optional parameters $T_{n+1}$ $p_{n+1}, \ldots, T_{n+k}$ $ p_{n+k}$. Then the type of $F$ is $(T_1 ,\ldots, T_n, \{T_{n+1}$ $p_ {n+1}, \ldots, T_{n+k}$ $p_{n+k}\}) \rightarrow T_0$.
843 867
844 \LMHash{} 868 \LMHash{}
845 The run time type of a function object always implements the class \cd{Function} . 869 The run time type of a function object always implements the class \cd{Function} .
(...skipping 1435 matching lines...) Expand 10 before | Expand all | Expand 10 after
2281 \end{dartCode} 2305 \end{dartCode}
2282 2306
2283 \commentary { 2307 \commentary {
2284 It is also a compile-time error to subclass, mix-in or implement an enum or to e xplicitly instantiate an enum. These restrictions are given in normative form i n sections \ref{superclasses}, \ref{superinterfaces}, \ref{mixinApplication} and \ref{instanceCreation} as appropriate. 2308 It is also a compile-time error to subclass, mix-in or implement an enum or to e xplicitly instantiate an enum. These restrictions are given in normative form i n sections \ref{superclasses}, \ref{superinterfaces}, \ref{mixinApplication} and \ref{instanceCreation} as appropriate.
2285 } 2309 }
2286 2310
2287 \section{Generics} 2311 \section{Generics}
2288 \LMLabel{generics} 2312 \LMLabel{generics}
2289 2313
2290 \LMHash{} 2314 \LMHash{}
2291 A class declaration (\ref{classes}) or type alias (\ref{typedef}) 2315 A class declaration (\ref{classes}), type alias (\ref{typedef}), or function (\r ef{functions}) $G$ may be {\em generic}, that is, $G$ may have formal type param eters declared.
2292 $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 act ual type parameters provided in the program. 2316 A declaration of a generic class or a generic type alias induces a family of dec larations, one for each actual type argument list provided in the program.
2317 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{genericFunc tionErasure}).
2293 2318
2294 \begin{grammar} 2319 \begin{grammar}
2295 {\bf typeParameter:} 2320 {\bf typeParameter:}
2296 metadata identifier (\EXTENDS{} type)? 2321 metadata identifier (\EXTENDS{} type)?
2297 . 2322 .
2298 {\bf typeParameters:} 2323 {\bf typeParameters:}
2299 `<' typeParameter (`,' typeParameter)* `>' 2324 `<' typeParameter (`,' typeParameter)* `>'
2300 . 2325 .
2301 \end{grammar} 2326 \end{grammar}
2302 2327
2303 \LMHash{} 2328 \LMHash{}
2304 A type parameter $T$ may be suffixed with an \EXTENDS{} clause that specifies th e {\em upper bound} for $T$. If no \EXTENDS{} clause is present, the upper boun d is \code{Object}. It is a static type warning if a type parameter is a supert ype of its upper bound. The bounds of type variables are a form of type annotati on and have no effect on execution in production mode. 2329 A type parameter $T$ may be suffixed with an \EXTENDS{} clause that specifies th e {\em upper bound} for $T$.
2330 If no \EXTENDS{} clause is present, the upper bound is \code{Object}.
2331 It is a static type warning if an actual type argument to a class or a type alia s is not a subtype of its upper bound.
2332 The bounds of type variables are a form of type annotation and have no effect on execution in production mode.
2305 2333
2306 \LMHash{} 2334 \LMHash{}
2307 Type parameters are declared in the type-parameter scope of a class. 2335 Type parameters are declared in the type-parameter scope of a class.
2308 The type parameters of a generic $G$ are in scope in the bounds of all of the ty pe parameters of $G$. The type parameters of a generic class declaration $G$ are also in scope in the \EXTENDS{} and \IMPLEMENTS{} clauses of $G$ (if these exis t) and in the body of $G$. However, a type parameter is considered to be a mal formed type when referenced by a static member. 2336 The type parameters of a generic $G$ are in scope in the bounds of all of the ty pe parameters of $G$. The type parameters of a generic class declaration $G$ are also in scope in the \EXTENDS{} and \IMPLEMENTS{} clauses of $G$ (if these exis t) and in the body of $G$. However, a type parameter is considered to be a mal formed type when referenced by a static member.
2309 2337
2310 \rationale{ 2338 \rationale{
2311 The restriction is necessary since a type variable has no meaning in the context of a static member, because statics are shared among all instantiations of a ge neric. However, a type variable may be referenced from an instance initializer, even though \THIS{} is not available. 2339 The restriction is necessary since a type variable has no meaning in the context of a static member, because statics are shared among all instantiations of a ge neric. However, a type variable may be referenced from an instance initializer, even though \THIS{} is not available.
2312 } 2340 }
2313 2341
2314 \commentary{ 2342 \commentary{
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
2401 2429
2402 %\Q{When does an interface injection take effect? When the containing library is loaded? 2430 %\Q{When does an interface injection take effect? When the containing library is loaded?
2403 %What is the scope of such a declaration? Is it global, or only in the scope of the containing library? The scope of such a declaration is global. 2431 %What is the scope of such a declaration? Is it global, or only in the scope of the containing library? The scope of such a declaration is global.
2404 %An injection must be at top level. Who has the right to inject an interface $I$ into another class $C$? Anybody? But since this affects dynamic behavior, is th is a weird security issue? 2432 %An injection must be at top level. Who has the right to inject an interface $I$ into another class $C$? Anybody? But since this affects dynamic behavior, is th is a weird security issue?
2405 %The current theory is that there is no security within an isolate, and one can never refer to a type from another isolate, so supposedly not an issue. This ass umption (no mutually suspicious code in the same isolate) is suspect but it seem s there is nothing to be done at this point. 2433 %The current theory is that there is no security within an isolate, and one can never refer to a type from another isolate, so supposedly not an issue. This ass umption (no mutually suspicious code in the same isolate) is suspect but it seem s there is nothing to be done at this point.
2406 %If libs are first class, they get created dynamically in order, and new libs mi ght modify the type relations among other libs types - but then it is clear when that happened and order is ok. 2434 %If libs are first class, they get created dynamically in order, and new libs mi ght modify the type relations among other libs types - but then it is clear when that happened and order is ok.
2407 %} 2435 %}
2408 2436
2409 %It is a compile-time error if a type $T$ appears more than once in the implemen ts or eextends clause of an interface injection. 2437 %It is a compile-time error if a type $T$ appears more than once in the implemen ts or eextends clause of an interface injection.
2410 2438
2439 \subsection{Generic Function Erasure}
2440 \LMLabel{genericFunctionErasure}
2441
2442 \commentary{
2443 Generic functions will be fully supported in a future version of the language.
2444 The current level of support allows programs using generic functions to be writt en, compiled, and executed.
2445 The type checks and dynamic semantics essentially erase the formal type paramete rs and actual type arguments.
2446 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.
2447 Type checking with full support for generic functions may then ensure some consi stency properties which remain valid also in this context.
2448 This section explains how generic function erasure works.
2449 }
2450
2451 \LMHash{}
2452 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}.
2453 A {\em non-generic function} is a function which is not generic.
2454
2455 \commentary{
2456 The following exceptions exist:
2457 Getter, setter, operator, and constructor declarations cannot be generic.
2458 }
2459
2460 \LMHash{}
2461 The formal type parameter list of a function introduces a new scope known as the function's {\em formal type parameter scope}.
2462 The formal type parameter scope of a generic function $f$ is enclosed in the sco pe where $f$ is declared.
2463 Every formal type parameter introduces a type into the formal type parameter sco pe.
2464
2465 \LMHash{}
2466 The formal type parameter scope of a function $f$ is the current scope for the r eturn type of $f$, if any, and for the formal type parameter list itself.
2467
2468 \commentary{
2469 This enables the use of F-bounded type parameters.
2470 Moreover, the formal type parameter scope is the enclosing scope for the formal parameter scope (\ref{formalParameters}), which enables usage of the type parame ters in type annotations in the parameter list, and in the body of the function.
2471 }
2472
2473 \LMHash{}
2474 { \def\Derased{\ensuremath{D_{\mbox{\scriptsize erased}}}}
2475 {\em Generic function erasure} takes as input a generic function declaration $D$ and either yields a non-generic function declaration \Derased{} or terminates w ith a compile-time error.
2476 \Derased{} is identical to $D$ except for the following replacements:
2477 \begin{itemize}
2478 \item The \GrammarSymbol{formalParameterPart} of \Derased{} is identical to the \GrammarSymbol{formalParameterList} of $D$.
2479 \commentary{That is, the type parameter list is erased.}
2480 \item Each occurrence in $D$ of an identifier $id$ which denotes a formal type p arameter is processed as follows:
2481 \begin{itemize}
2482 \item If $id$ occurs as \code{$e$ \IS{} $id$} or \code{$e$ \IS{}! $id$} for so me expression $e$, or if $id$ occurs as a type literal, a compile-time error occ urs.
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
2483 \item In all other cases, the location corresponding to $id$ in \Derased{} con tains \DYNAMIC{}.
2484 \end{itemize}
2485 \end{itemize}
2486 }
2487
2488 \commentary{
2489 This means that formal type parameters in a generic function work like \DYNAMIC{ } when used as type annotations.
2490 This is also the case when they are used as type arguments, both in type annotat ions 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
2491 For example, \code{\RETURN{} <T>[];} will return a \code{List<\DYNAMIC{}>}.
2492 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{}.
2493 }
2494
2495 \rationale{
2496 The check associated with a cast to a type parameter of a generic function is om itted because such checks are almost always expected to succeed.
2497 This may introduce bugs in failure handling, so a more defensive style of progra mming may be needed around such casts.
2498 In contrast, an is-expression may yield \TRUE{} as well as \FALSE{} during norma l processing, and it could silently introduce bugs into correct programs if we h ad chosen to always evaluate these is-expressions to a fixed value like \TRUE{}.
2499 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
2500 }
2411 2501
2412 \section{Metadata} 2502 \section{Metadata}
2413 \LMLabel{metadata} 2503 \LMLabel{metadata}
2414 2504
2415 \LMHash{} 2505 \LMHash{}
2416 Dart supports metadata which is used to attach user defined annotations to progr am structures. 2506 Dart supports metadata which is used to attach user defined annotations to progr am structures.
2417 2507
2418 \begin{grammar} 2508 \begin{grammar}
2419 {\bf metadata:} 2509 {\bf metadata:}
2420 (`@' qualified ({\escapegrammar `.'} identifier)? (arguments)?)* 2510 (`@' qualified ({\escapegrammar `.'} identifier)? (arguments)?)*
(...skipping 803 matching lines...) Expand 10 before | Expand all | Expand 10 after
3224 3314
3225 3315
3226 \subsection{ Function Expressions} 3316 \subsection{ Function Expressions}
3227 \LMLabel{functionExpressions} 3317 \LMLabel{functionExpressions}
3228 3318
3229 \LMHash{} 3319 \LMHash{}
3230 A {\em function literal} is an object that encapsulates an executable unit of co de. 3320 A {\em function literal} is an object that encapsulates an executable unit of co de.
3231 3321
3232 \begin{grammar} 3322 \begin{grammar}
3233 {\bf functionExpression:} 3323 {\bf functionExpression:}
3234 formalParameterList functionBody 3324 formalParameterPart functionBody
3235 . 3325 .
3236 \end{grammar} 3326 \end{grammar}
3237 3327
3238 \LMHash{} 3328 \LMHash{}
3239 The class of a function literal implements the built-in class \code{Function}. 3329 The class of a function literal implements the built-in class \code{Function}.
3240 %Invoking the getter \code{runtimeType} on a function literal returns the \code{ Type} object that is the value of the expression \code{Function}. 3330 %Invoking the getter \code{runtimeType} on a function literal returns the \code{ Type} object that is the value of the expression \code{Function}.
3241 % not necessarily 3331 % not necessarily
3242 3332
3243
3244 %Q{Can anyone implement it? Then we should define things via call} 3333 %Q{Can anyone implement it? Then we should define things via call}
3245 3334
3246 \LMHash{} 3335 \LMHash{}
3247 The static type of a function literal of the form 3336 The static type of a function literal of the form
3248 3337
3249 $(T_1$ $a_1, \ldots, T_n$ $a_n, [T_{n+1}$ $x_{n+1} = d_1, \ldots, T_{n+k}$ $x_{ n+k} = d_k]) => e$ 3338 $(T_1$ $a_1, \ldots, T_n$ $a_n, [T_{n+1}$ $x_{n+1} = d_1, \ldots, T_{n+k}$ $x_{ n+k} = d_k]) => e$
3250 is 3339 is
3251 3340
3252 $(T_1 \ldots, T_n, [T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}]) \rightarrow T _0$, where $T_0$ is the static type of $e$. 3341 $(T_1 \ldots, T_n, [T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}]) \rightarrow T _0$, where $T_0$ is the static type of $e$.
3253 3342
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after
3674 \commentary{ 3763 \commentary{
3675 As discussed in section \ref{errorsAndWarnings}, the handling of a suspended iso late is the responsibility of the embedder. 3764 As discussed in section \ref{errorsAndWarnings}, the handling of a suspended iso late is the responsibility of the embedder.
3676 } 3765 }
3677 3766
3678 3767
3679 3768
3680 \subsection{ Function Invocation} 3769 \subsection{ Function Invocation}
3681 \LMLabel{functionInvocation} 3770 \LMLabel{functionInvocation}
3682 3771
3683 \LMHash{} 3772 \LMHash{}
3684 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 construc tor is invoked (either via instance creation (\ref{instanceCreation}), construct or redirection (\ref{redirectingConstructors}) or super initialization). The var ious 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$ h as been determined, the formal parameters of $f$ are bound to corresponding actu al arguments. When the body of $f$ is executed it will be executed with the afor ementioned bindings. 3773 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 construct or is invoked (either via instance creation (\ref{instanceCreation}), constructo r redirection (\ref{redirectingConstructors}) or super initialization).
3774 The various kinds of function invocation differ as to how the function to be inv oked, $f$, is determined, as well as whether \THIS{} (\ref{this}) is bound.
3775 Once $f$ has been determined, the formal parameters of $f$ are bound to correspo nding actual arguments.
3776 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
3777 When the body of $f$ is executed it will be executed with the aforementioned bin dings.
3685 3778
3686 \LMHash{} 3779 \LMHash{}
3687 If $f$ is synchronous and is not a generator (\ref{functions}) then execution of the body of $f$ begins immediately. 3780 If $f$ is synchronous and is not a generator (\ref{functions}) then execution of the body of $f$ begins immediately.
3688 If the execution of the body of $f$ returns a value, $v$, (\ref{completion}), th e invocation evaluates to $v$. 3781 If the execution of the body of $f$ returns a value, $v$, (\ref{completion}), th e invocation evaluates to $v$.
3689 If the execution completes normally or it returns without a value, the invocatio n evaluates to \NULL (\ref{null}). 3782 If the execution completes normally or it returns without a value, the invocatio n evaluates to \NULL (\ref{null}).
3690 If the execution throws an exception object and stack trace, the invocation thro ws the same exception object and stack trace (\ref{evaluation}). 3783 If the execution throws an exception object and stack trace, the invocation thro ws the same exception object and stack trace (\ref{evaluation}).
3691 3784
3692 \commentary{ 3785 \commentary{
3693 A complete function body can never break or contine (\ref{completion}) 3786 A complete function body can never break or contine (\ref{completion})
3694 because a \BREAK{} or \CONTINUE{} statement must always occur inside the stateme nt that is the target of the \BREAK{} or \CONTINUE{}. 3787 because a \BREAK{} or \CONTINUE{} statement must always occur inside the stateme nt that is the target of the \BREAK{} or \CONTINUE{}.
3695 This means that a function body can only either complete normally, throw, or ret urn. Completing normally or returning without a value is treated the same as ret urning \NULL, so the result of executing a function body can always be used as t he result of evaluating an expression, either by evaluating to a value or by the evaluation throwing. 3788 This means that a function body can only either complete normally, throw, or ret urn. Completing normally or returning without a value is treated the same as ret urning \NULL, so the result of executing a function body can always be used as t he result of evaluating an expression, either by evaluating to a value or by the evaluation throwing.
3696 } 3789 }
3697 3790
3698 3791
3699 \LMHash{} 3792 \LMHash{}
3700 If $f$ is marked \SYNC* (\ref{functions}), then a fresh instance $i$ implementin g the built-in class \code{Iterable} is associated with the invocation and immed iately returned. 3793 If $f$ is marked \SYNC* (\ref{functions}), then a fresh instance $i$ implementin g the built-in class \code{Iterable} is associated with the invocation and immed iately returned.
3701 3794
3702 \commentary{ 3795 \commentary{
3703 A Dart implementation will need to provide a specific implementation of \code{It erable} that will be returned by \SYNC* methods. A typical strategy would be to produce an instance of a subclass of class \code{IterableBase} defined in \code{ dart:core}. The only method that needs to be added by the Dart implementation in that case is \code{iterator}. 3796 A Dart implementation will need to provide a specific implementation of \code{It erable} that will be returned by \SYNC* methods. A typical strategy would be to produce an instance of a subclass of class \code{IterableBase} defined in \code{ dart:core}. The only method that needs to be added by the Dart implementation in that case is \code{iterator}.
3704 } 3797 }
3705 3798
3706 \LMHash{} 3799 \LMHash{}
3707 The iterable implementation must comply with the contract of \code{Iterable} and should not take any steps identified as exceptionally efficient in that contrac t. 3800 The iterable implementation must comply with the contract of \code{Iterable} and should not take any steps identified as exceptionally efficient in that contrac t.
3708 3801
3709 \commentary { 3802 \commentary {
3710 The contract explicitly mentions a number of situations where certain iterables could be more efficient than normal. For example, by precomputing their length. Normal iterables must iterate over their elements to determine their length. Thi s is certainly true in the case of a synchronous generator, where each element i s computed by a function. It would not be acceptable to pre-compute the results of the generator and cache them, for example. 3803 The contract explicitly mentions a number of situations where certain iterables could be more efficient than normal. For example, by precomputing their length. Normal iterables must iterate over their elements to determine their length. Thi s is certainly true in the case of a synchronous generator, where each element i s computed by a function. It would not be acceptable to pre-compute the results of the generator and cache them, for example.
3711 } 3804 }
3712 3805
3713 \LMHash{} 3806 \LMHash{}
3714 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}, 3807 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}),
3715 \begin{itemize} 3808 \begin{itemize}
3716 \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{nu ll} and the current call to \code{moveNext()} on $j$ returns false, as must all further calls. 3809 \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{nu ll} and the current call to \code{moveNext()} on $j$ returns false, as must all further calls.
3717 \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. 3810 \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.
3718 \end{itemize} 3811 \end{itemize}
3719 3812
3720 Each iterator starts a separate computation. If the \SYNC* function is impure, t he sequence of values yielded by each iterator may differ. 3813 Each iterator starts a separate computation. If the \SYNC* function is impure, t he sequence of values yielded by each iterator may differ.
3721 3814
3722 \commentary{ 3815 \commentary{
3723 One can derive more than one iterator from a given iterable. Note that operati ons on the iterable itself can create distinct iterators. An example would be \c ode{length}. It is conceivable that different iterators might yield sequences o f different length. The same care needs to be taken when writing \SYNC* function s as when 3816 One can derive more than one iterator from a given iterable. Note that operati ons on the iterable itself can create distinct iterators. An example would be \c ode{length}. It is conceivable that different iterators might yield sequences o f different length. The same care needs to be taken when writing \SYNC* function s as when
3724 writing an \code{Iterator} class. In particular, it should handle multiple 3817 writing an \code{Iterator} class. In particular, it should handle multiple
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
3776 % expressionList ',' spreadArgument; 3869 % expressionList ',' spreadArgument;
3777 expressionList (`,' namedArgument)* 3870 expressionList (`,' namedArgument)*
3778 % spreadArgument 3871 % spreadArgument
3779 . 3872 .
3780 3873
3781 {\bf namedArgument:} 3874 {\bf namedArgument:}
3782 label expression % could be top level expression? 3875 label expression % could be top level expression?
3783 . 3876 .
3784 \end{grammar} 3877 \end{grammar}
3785 3878
3786 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 s ame parameter list without the trailing comma. All argument lists in this specif ication are shown without a trailing comma, but the rules and semantics apply eq ually to the corresponding argument list with a trailing comma. 3879 \LMHash{}
3880 Argument lists allow an optional trailing comma after the last argument ($`,'?$) .
3881 An argument list with such a trailing comma is equivalent in all ways to the sam e argument list without the trailing comma.
3882 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.
3883
3884 \LMHash{}
3885 When parsing an argument list, an ambiguity may arise because the same source co de could be one generic function invocation, and it could be two or more relatio nal expressions and/or shift expressions.
3886 In this situation, the expression is always parsed as a generic function invocat ion.
Lasse Reichstein Nielsen 2017/03/06 15:09:33 The ambiguity is not just in argument lists, it's
3887
3888 % Should we specify the precise disambiguation rule here?:
3889 % We have seen 'a', '<', a matching '>', and '(', where
3890 % 'a' is tricky because we can have things like 'new Foo().m<...>(...',
3891 % 'x..y(...).m<...>(...', etc, basically everything that can precede
3892 % argumentPart in the grammar.
Lasse Reichstein Nielsen 2017/03/06 15:09:34 We should specify which programs are valid, and wh
3893
3894 \commentary{
3895 An example is \code{f(a<B, C>($d$))}, which may be an invocation of \code{f} pas sing two actual arguments of type \code{bool}, or an invocation of \code{f} pass ing 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
3896 Note that the ambiguity may be eliminated by omitting the parentheses around the expression $d$, or adding parentheses around one of the relational expressions.
3897 }
3898
3899 \rationale{
3900 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.
3901 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.
3902 }
3787 3903
3788 \LMHash{} 3904 \LMHash{}
3789 Evaluation of an actual argument list of the form 3905 Evaluation of an actual argument list of the form
3790 3906
3791 $(a_1, \ldots, a_m, q_1: a_{m+1}, \ldots, q_l: a_{m+l})$ 3907 $(a_1, \ldots, a_m, q_1: a_{m+1}, \ldots, q_l: a_{m+l})$
3792 3908
3793 proceeds as follows: 3909 proceeds as follows:
3794 3910
3795 \LMHash{} 3911 \LMHash{}
3796 The arguments $a_1, \ldots, a_{m+l}$ are evaluated in the order they appear in t he program, producing objects $o_1, \ldots, o_{m+l}$. 3912 The arguments $a_1, \ldots, a_{m+l}$ are evaluated in the order they appear in t he program, producing objects $o_1, \ldots, o_{m+l}$.
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
4076 4192
4077 \subsubsection{Cascaded Invocations} 4193 \subsubsection{Cascaded Invocations}
4078 \LMLabel{cascadedInvocations} 4194 \LMLabel{cascadedInvocations}
4079 4195
4080 \LMHash{} 4196 \LMHash{}
4081 A {\em cascaded method invocation} has the form \code{$e$..\metavar{suffix}} 4197 A {\em cascaded method invocation} has the form \code{$e$..\metavar{suffix}}
4082 where $e$ is an expression and \metavar{suffix} is a sequence of operator, metho d, getter or setter invocations. 4198 where $e$ is an expression and \metavar{suffix} is a sequence of operator, metho d, getter or setter invocations.
4083 4199
4084 \begin{grammar} 4200 \begin{grammar}
4085 {\bf cascadeSection:} 4201 {\bf cascadeSection:}
4086 `{\escapegrammar ..}' (cascadeSelector arguments*) (assignableSelector arg uments*)* (assignmentOperator expressionWithoutCascade)? 4202 `{\escapegrammar ..}' (cascadeSelector argumentPart*) (assignableSelector argumentPart*)* (assignmentOperator expressionWithoutCascade)?
4087 . 4203 .
4088 4204
4089 {\bf cascadeSelector:}`[' expression `]'; 4205 {\bf cascadeSelector:}`[' expression `]';
4090 identifier 4206 identifier
4091 . 4207 .
4208
4209 {\bf argumentPart:}
4210 typeArguments? arguments
4211 .
4092 \end{grammar} 4212 \end{grammar}
4093 4213
4094 \LMHash{} 4214 \LMHash{}
4095 Evaluation of a cascaded method invocation expression $e$ of the form \code{$e$. .\metavar{suffix}} proceeds as follows: 4215 Evaluation of a cascaded method invocation expression $e$ of the form \code{$e$. .\metavar{suffix}} proceeds as follows:
4096 4216
4097 Evaluate $e$ to an object $o$. 4217 Evaluate $e$ to an object $o$.
4098 Let $t$ be a fresh variable bound to $o$. 4218 Let $t$ be a fresh variable bound to $o$.
4099 Evaluate \code{$t$.\metavar{suffix}} to an object. 4219 Evaluate \code{$t$.\metavar{suffix}} to an object.
4100 Then $e$ evaluates to $o$. 4220 Then $e$ evaluates to $o$.
4101 4221
(...skipping 1007 matching lines...) Expand 10 before | Expand all | Expand 10 after
5109 \begin{grammar} 5229 \begin{grammar}
5110 {\bf postfixExpression:}assignableExpression postfixOperator; 5230 {\bf postfixExpression:}assignableExpression postfixOperator;
5111 primary selector* 5231 primary selector*
5112 . 5232 .
5113 5233
5114 {\bf postfixOperator:} 5234 {\bf postfixOperator:}
5115 incrementOperator 5235 incrementOperator
5116 . 5236 .
5117 5237
5118 {\bf selector:}assignableSelector; 5238 {\bf selector:}assignableSelector;
5119 arguments 5239 argumentPart
5120 . 5240 .
5121 5241
5122 {\bf incrementOperator:}`++'; 5242 {\bf incrementOperator:}`++';
5123 `-{}-' 5243 `-{}-'
5124 . 5244 .
5125 5245
5126 \end{grammar} 5246 \end{grammar}
5127 5247
5128 \LMHash{} 5248 \LMHash{}
5129 A {\em postfix expression} is either a primary expression, a function, method o r getter invocation, or an invocation of a postfix operator on an expression $e$ . 5249 A {\em postfix expression} is either a primary expression, a function, method o r getter invocation, or an invocation of a postfix operator on an expression $e$ .
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
5289 This section describes how to evaluate these expressions when they do not consti tute the complete left hand side of an assignment. 5409 This section describes how to evaluate these expressions when they do not consti tute the complete left hand side of an assignment.
5290 5410
5291 \rationale{ 5411 \rationale{
5292 Of course, if assignable expressions always appeared {\em as} the left hand side , one would have no need for their value, and the rules for evaluating them woul d be unnecessary. However, assignable expressions can be subexpressions of othe r expressions and therefore must be evaluated. 5412 Of course, if assignable expressions always appeared {\em as} the left hand side , one would have no need for their value, and the rules for evaluating them woul d be unnecessary. However, assignable expressions can be subexpressions of othe r expressions and therefore must be evaluated.
5293 } 5413 }
5294 5414
5295 5415
5296 5416
5297 \begin{grammar} 5417 \begin{grammar}
5298 5418
5299 {\bf assignableExpression:}primary (arguments* assignableSelector)+; 5419 {\bf assignableExpression:}primary (argumentPart* assignableSelector)+;
5300 \SUPER{} unconditionalAssignableSelector; 5420 \SUPER{} unconditionalAssignableSelector;
5301 identifier 5421 identifier
5302 . 5422 .
5303 5423
5304 {\bf unconditionalAssignableSelector:}`[' expression `]'; % again, could be top level 5424 {\bf unconditionalAssignableSelector:}`[' expression `]'; % again, could be top level
5305 `{\escapegrammar .}' identifier 5425 `{\escapegrammar .}' identifier
5306 . 5426 .
5307 5427
5308 {\bf assignableSelector:} 5428 {\bf assignableSelector:}
5309 unconditionalAssignableSelector; 5429 unconditionalAssignableSelector;
5310 `{\escapegrammar ?.}' identifier 5430 `{\escapegrammar ?.}' identifier
5311 . 5431 .
5312
5313 \end{grammar} 5432 \end{grammar}
5314 5433
5315 5434
5316 \LMHash{} 5435 \LMHash{}
5317 An {\em assignable expression} is either: 5436 An {\em assignable expression} is either:
5318 \begin{itemize} 5437 \begin{itemize}
5319 \item An identifier. 5438 \item An identifier.
5320 \item An invocation (possibly conditional) of a getter (\ref{getters}) or list a ccess operator on an expression $e$. 5439 \item An invocation (possibly conditional) of a getter (\ref{getters}) or list a ccess operator on an expression $e$.
5321 \item An invocation of a getter or list access operator on \SUPER{}. 5440 \item An invocation of a getter or list access operator on \SUPER{}.
5322 \end{itemize} 5441 \end{itemize}
(...skipping 2790 matching lines...) Expand 10 before | Expand all | Expand 10 after
8113 8232
8114 The invariant that each normative paragraph is associated with a line 8233 The invariant that each normative paragraph is associated with a line
8115 containing the text \LMHash{} should be maintained. Extra occurrences 8234 containing the text \LMHash{} should be maintained. Extra occurrences
8116 of \LMHash{} can be added if needed, e.g., in order to make 8235 of \LMHash{} can be added if needed, e.g., in order to make
8117 individual \item{}s in itemized lists addressable. Each \LM.. command 8236 individual \item{}s in itemized lists addressable. Each \LM.. command
8118 must occur on a separate line. \LMHash{} must occur immediately 8237 must occur on a separate line. \LMHash{} must occur immediately
8119 before the associated paragraph, and \LMLabel must occur immediately 8238 before the associated paragraph, and \LMLabel must occur immediately
8120 after the associated \section{}, \subsection{} etc. 8239 after the associated \section{}, \subsection{} etc.
8121 8240
8122 ---------------------------------------------------------------------- 8241 ----------------------------------------------------------------------
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698