# slebok/zoo

Fetching contributors…
Cannot retrieve contributors at this time
6175 lines (4075 sloc) 345 KB
 \documentclass{article} \usepackage{epsfig} \usepackage{dart} \usepackage{bnf} \usepackage{hyperref} \newcommand{\code}[1]{{\sf #1}} \title{Dart Programming Language Specification \\ {\large Draft Version 0.71}} \author{The Dart Team} \begin{document} \maketitle \tableofcontents \newpage \pagestyle{myheadings} \markright{{\bf Draft} Dart Programming Language Specification {\bf Draft}} \section{Notes} Expect the contents and language rules to change over time. %Please mail comments to gbracha@google.com. \subsection{Licensing} \label{licensing} Except as otherwise noted at http://code.google.com/policies.html\#restrictions, the content of this document is licensed under the Creative Commons Attribution 3.0 License available at: http://creativecommons.org/licenses/by/3.0/ and code samples are licensed under the BSD license available at http://code.google.com/google\_bsd\_license.html. \subsection{Change Log} \label{changes} \subsubsection{Changes Since Version 0.02} The following changes have been made in version 0.03 since version 0.02. In addition, various typographical errors have been corrected. The changes are listed by section number. \ref{notation}: Expanded examples of grammar. \ref{factories}: Corrected reference to undefined production {\em typeVariables} to {\em typeParameters}. \ref{superinterfaces}: Removed static warning when imported superinterface of a class contains private members. The former section on factories and constructors in interfaces (now removed): Removed redundant prohibition on default values. \ref{interfaceSuperinterfaces}: Removed static warning when imported superinterface of an interface contains private members. \ref{expressions}: Fixed typo in grammar. \ref{new}, \ref{const} : made explicit accessibility requirement for class being constructed. \ref{const}: make clear that referenced constructor must be marked \CONST{}. \ref{superInvocation}: fixed botched sentence where superclass $S$ is introduced. \ref{postfixExpressions}: qualified definition of $v++$ so it is clear that $v$ is an identifier. \subsubsection{Changes Since Version 0.03} \ref{instanceMethods}. The former section on interface methods (now removed): Added missing requirement that overriding methods have same number of required parameters and all optional parameters as overridden method, in same order. \ref{generics}: Added prohibition against cyclic type hierarchy for type parameters. \ref{instanceCreation}: Clarified requirements on use of parameterized types in instance creation expressions. \ref{bindingActualsToFormals}: Added requirement that $q_i$ are distinct. \ref{staticInvocation}. Static method invocation determines the function (which may involve evaluating a getter) before evaluating the arguments, so that static invocation and top-level function invocation agree. \ref{typeTest}: Added missing test that type being tested against is in scope and is indeed a type. \ref{forLoop}: Changed for loop to introduce fresh variable for each iteration. \ref{parameterizedTypes}: Malformed parameterized types generate warnings, not errors(except when used in reified contexts like instance creation and superclasses/interfaces). \subsubsection{Changes Since Version 0.04} Added hyperlinks in PDF. \ref{operators}: Removed unary plus operator. Clarified that operator formals must be required. \ref{constantConstructors}: Filled in a lot of missing detail. The former section on factories and constructors in interfaces (now removed): Allowed factory class to be declared via a qualified name. \ref{numbers}: Changed production for $Number$. \ref{const}: Added requirements that actuals be constant, rules for dealing with inappropriate types of actuals, and examples. Also explicitly prohibit type parameters. \ref{functionExpressionInvocation}: Modified final bullet to keep it inline with similar clauses in other sections. Exact wording of these sections also tweaked slightly. \ref{unaryExpressions}: Specified ! operator. Eliminated section on prefix expressions and moved contents to section on unary expressions. \ref{lexicalRules}: Specified unicode form of Dart source. \subsubsection{Changes Since Version 0.05} \ref{generativeConstructors}: Clarified how initializing formals can act as optional parameters of generative constructors. \ref{factories}: Treat factories as constructors, so type parameters are implicitly in scope. The former section on factories and constructors in interfaces (now removed): Simplify rules for interface factory clauses. Use the keyword \DEFAULT{} instead of \FACTORY{}. \ref{generics}: Mention that typedefs can have type parameters. \ref{typeTest}: Added checked mode test that type arguments match generic type. \ref{dynamicTypeSystem}: Added definition of malformed types, and requirement on their handling in checked mode. \subsubsection{Changes Since Version 0.06} \ref{variables}: library variable initializers must be constant. \ref{classes}: Added \ABSTRACT{} modifier to grammar. \ref{classes}, \ref{staticMethods}, \ref{staticVariables}, \ref{unqualifiedInvocation},\ref{identifierReference}: Superclass static members are not in scope in subclasses, and do not conflict with subclass members. \ref{operators}: \code{[]=} must return \VOID{}. Operator \CALL{} added to support function emulation. Removed operator \code{$>>>$}. Made explicit restriction on methods named \CALL{} or \NEGATE{}. \ref{constants}: Added \code{!$e$} as constant expression. Clarified what happens if evaluation of a constant fails. \ref{maps}: Map keys need not be constants. However, they are always string literals. \ref{this}: State restrictions on use of \THIS{}. \ref{instanceCreation}, \ref{new}: Rules for bounds checking of constructor arguments when calling default constructors for interfaces refined. \ref{ordinaryInvocation}: Revised semantics to account for function emulation. \ref{staticInvocation}: Revised semantics to account for function emulation. \ref{superInvocation}: Factory constructors cannot contain super invocations. Revised semantics to account for function emulation. \ref{assignment}: Specified assignment involving \code{[]=} operator. \ref{compoundAssignment}: Removed operator \code{$>>>$}. \ref{shift}: Removed operator \code{$>>>$}. \ref{postfixExpressions}: Postfix \code{-{}-} operator specified. Behavior of postfix operations on subscripted expressions specified. \ref{identifierReference}: Added built-in identifier \CALL{}. Banned use of built-in identifiers as types made other uses warnings. \ref{typeTest}: Moved specification of test that type arguments match generic type to \ref{dynamicTypeSystem}. \ref{switch}: Corrected evaluation of case clauses so that case expression is the receiver of ==. Revised specification to correctly deal with blank statements in case clauses. \ref{assert}: Fixed bug in \ASSERT{} specification that could lead to puzzlers. \ref{dynamicTypeSystem}: Consolidated definition of malformed types. \ref{functionTypes}: Revised semantics to account for function emulation. \subsubsection{Changes Since Version 0.07} \ref{variables}: Static variables are lazily initialized, but need not be constants. Orthogonal notion of constant variable introduced. \ref{operators}: Added \EQUALS{} operator as part of revised \code{==} treatment. \ref{generativeConstructors}: Initializing formals have the same type as the field they correspond to. \ref{staticVariables}: Static variable getter rules revised to deal with lazy initialization. \ref{expressions}: Modified syntax to support cascaded method invocations. \ref{constants}: Removed support for + operator on Strings. Extended string constants to support certain cases of string interpolation. Revised constants to deal with constant variables. \ref{strings}: Corrected definition of \code{HEX\_DIGIT\_SEQUENCE}. Support implicit concatenation of adjacent single line strings. \ref{bindingActualsToFormals}: Centralized and corrected type rules for function invocation. \ref{methodInvocation}: Moved rules for checking function/method invocations to \ref{bindingActualsToFormals}. Added definition of cascaded method invocations. \ref{getterInvocation}, \ref{assignment}: Updated \code{noSuchMethod()} call for getters and setters to conform to planned API. \ref{conditional}: Modified syntax to support cascaded method invocations. \ref{equality}: Revised semantics for \code{==}. \ref{identifierReference}: Removed \IMPORT{}, \LIBRARY{} and \SOURCE{} from list of built-in identifiers and added \EQUALS{}. Revised rules for evaluating identifiers to deal with lazy static variable initialization. \ref{continue}: Fixed bug that allowed \CONTINUE{} labeled on non-loops. \ref{librariesAndScripts}: Revised syntax so no space is permitted between \code{\#} and directives. Introduced \code{show:} combinator. Describe \code{prefix:} as a combinator. Added initial discussion of namespaces. Preclude string interpolation in arguments to directives. \subsubsection{Changes Since Version 0.08} \ref{instanceMethods}, \ref{abstractInstanceMembers}: Abstract methods may specify default values. \ref{interfaces}, The former section on interface methods (now removed): Interface methods may specify default values. \ref{constants}: The \code{\~{}/ } operator can apply to doubles. \ref{instanceCreation}: Refined rules regarding abstract class instantiation, allowing factories to be used. \ref{switch}: \SWITCH{} statement specification revised. \ref{throw}: \THROW{} may not throw \NULL{}. \ref{imports}: Imports introduce a scope separate from the library scope. Multiple libraries may share prefix. \ref{typedef}: Recursive typedefs disallowed. \subsubsection{Changes Since Version 0.09} \ref{scoping}: Consolidated discussion of namespaces and scopes. Started to tighten up definitions of scopes. \ref{classes}: Overriding of fields allowed. \ref{operators}: \CALL{} is no longer an operator. The former section on variables in interfaces (now removed): Added specification of variable declarations in interfaces. \ref{constants}: Static methods and top-level functions are compile-time constants. \ref{strings}: Multiline strings can be implicitly concatenated and contain interpolated expressions. \ref{typeCast}: Type cast expression added. \ref{expressionStatements}: Map literals cannot be expression statements. \ref{try}, \ref{throw}: Clarified type of stack trace. \ref{exports}, \ref{imports}: Added re-export facility. \subsubsection{Changes Since Version 0.10} \ref{overview}: Discuss reified runtime types. \ref{scoping}: Removed shadowing warnings. Allow overloading of \code{-}. \ref{variables}: Centralized discussion of implicit getters and setters. \ref{externalFunctions}: External functions added. \ref{classes}: Abstract classes must now be declared explicitly. \ref{operators}: Eliminate \NEGATE{} in favor of overloaded unary minus. Eliminate \EQUALS{} in favor of operator \code{==}. \ref{setters}: Setter syntax no longer includes = sign after the name. \ref{abstractInstanceMembers}: Clarify that getters and setters may be abstract. Eliminate \ABSTRACT{} modifier for abstract members. Added static warning if abstract class has abstract member. \ref{instanceVariables}: Instance variables can be initialized to non-constants. Moved discussion of implicit getters and setters to \ref{variables}. \ref{generativeConstructors}: Clarify that finals can only be set once. \ref{redirectingFactoryConstructors}: Added redirecting factories. \ref{staticVariables}: Moved discussion of implicit getters and setters to \ref{variables}. \ref{interfaces}: Eliminated interface declarations. \ref{metadata}: Added metadata. \ref{constants}: Refined definition constant identity/caching. \ref{throw}: Stack traces moved to \ref{try}. \ref{new}: Creating an instance via \NEW{} using an undefined class or constructor is a dynamic error and a static warning, not a compile-time error. Evaluation rules to allow instance variables with non-constant initializers. Instantiating an abstract class via a generative constructor is now a dynamic error. \ref{equality}: Replaced \code{===} with built-in function \code{identical()}. Equality does not special case identity. \ref{identifierReference}: Type names have meaning as expressions. \ASSERT{} is not a built-in identifier anymore, but \EXPORT{}, \IMPORT{}, \LIBRARY{} and \PART{} are. Removed warning on use of built-in identifiers as variable/function names. \ref{typeCast}: type cast accepts \NULL{}. \ref{argumentDefinitionTest}: Added operation to determine if optional argument was actually passed. \ref{localFunctionDeclaration}: Added section on local functions. \ref{switch}: Allow switch on compile-time constants of any one type. \ref{try}: Revised syntax for \CATCH{} clauses. Specification of stack traces moved from \ref{throw}. \ref{return}: Made explicit that checked mode tests returns. \ref{assert}: \ASSERT{} is now a reserved word. \ref{librariesAndScripts}: Revised library syntax and semantics. \ref{typeDynamic}: Renamed {\bf Dynamic} to \DYNAMIC{}. \ref{reservedWords}: \ASSERT{} is a reserved word. \subsubsection{Changes Since Version 0.11} \ref{notation}: Moved discussion of tokenization to section \ref{reference}. \ref{numbers}: Removed unary plus. \ref{librariesAndScripts}: Refined definition of show and hide to handle getters and setters in pairs. \ref{functionTypes}: All function types are subtypes of \code{Function}. \ref{reference}: Added discussion of tokenization. \ref{reservedWords}: Defined meaning of reserved word. \ref{comments}: Added initial discussion of dartdoc comments. \subsubsection{Changes Since Version 0.12} \ref{classes}: Removed \ABSTRACT{} modifier from grammar of members. Added grammar for \WITH{} clause. \ref{superclasses}: Added discussion of new \WITH{} clause for mixins. \ref{mixins}: Added specification of mixins. \ref{constants}: Revised description of \code{identical()} so that it always returns \TRUE{} on numbers with the same class and value. \ref{null}: Invocations on \NULL{} throw \code{NoSuchMethodError} only. \ref{throw}: \THROW{} of \NULL{} raises \code{NullThrownError}. \ref{instanceCreation} Using undefined types as type arguments to a constructor is a dynamic failure. \ref{librariesAndScripts}: Added discussion of compilation units. Allow name clause to be optional for libraries, allow export clauses in scripts. Support fully qualified name for libraries. Allow different imports to share same prefix. Added mixin application as a top level declaration. \ref{typedef}: Typedefs for mixin applications added. \ref{interfaceTypes}: Add effects of mixin clause on subtyping. \ref{leastUpperBounds}: Corrected definition of LUBs. \ref{reservedWords}: Added keyword \WITH{}. \subsubsection{Changes Since Version 0.20} \ref{getters}: Getters cannot return \VOID{}. \ref{superinterfaces}: Added requirement that superclass cannot appear in \IMPLEMENTS{} clause. \ref{interfaceInheritanceAndOverriding}: Clarified status of getter/setter vs. method conflicts in multiple interface inheritance. \ref{throw}: Separated \THROW{} into \code{\THROW{} e} and \code{\RETHROW{}}. \ref{new}: Arguments to constructor are evaluated before allocating new object. \ref{unqualifiedInvocation}: Calling an undeclared method in a static context is a dynamic error (and a static warning) not a compile-time one. \ref{ordinaryInvocation}, \ref{superInvocation}, \ref{getterInvocation}, \ref{assignment}: Refined description of \code{InvocationMirror} instance passed to \code{noSuchMethod()}. \ref{lexicalRules}: Abandoned requirement for Unicode Normalization Form C. \subsubsection{Changes Since Version 0.30} \ref{superclasses}, \ref{superinterfaces}: Clarified that super types with wrong number of type arguments cause a compilation error. \subsubsection{Changes Since Version 0.31} \ref{abstractInstanceMembers}: Abstract methods act as pure declarations. \ref{mixins}: Mixin application has forwarding constructors for all superclass constructors. \ref{instanceCreation}, \ref{new}: Revised so that wrong generic arity is a runtime error with static warning. \ref{typeTest}, \ref{typeCast}: Eliminated special treatment of malformed types. \ref{rethrow}: Rethrow is a statement, not an expression. \ref{librariesAndScripts}: Semicolon required after top-level external declarations. \ref{imports}: Removed requirement that library names be unique within an isolate. \ref{dynamicTypeSystem}: Revised definition of malformed types. Revised behavior of checked and production modes wrt to malformed and malbounded types. Refined assignability rules wrt new function type subtyping. \ref{interfaceTypes}: Corrected oversight wrt type variables and \cd{Object}. \ref{functionTypes}: Liberalized function subtyping rules. Special assignability rules. \ref{parameterizedTypes}: Out with misconstructed types, in with malbounded ones. \subsubsection{Changes Since Version 0.40} \ref{expressions}: Argument definition test construct dropped. \ref{maps}: Map literals can be keyed by arbitrary expressions. \ref{librariesAndScripts}: Implicitly named libraries are named '. Script tags are allowed in all libraries. It is a warning to import or export two libraries with the same name. \subsubsection{Changes Since Version 0.41} \ref{variables}: Uninitialized final is now just a static warning. \ref{typeOfAFunction}: Added details about the run time type of functions. \ref{instanceVariables}: Disallowed const inst vars. \ref{redirectingConstructors}: Uninitialized final is now just a static warning. \ref{objectIdentity}, \ref{constants}: Clarified rules for double identity. \ref{maps}: Adjusted rules for constant map literals. \ref{propertyExtraction}: If the same method is extracted repeatedly from the same object, the results are equal. Furthermore, the type of the property extraction is based on the method being closurized. Also described handling of property extractions on \SUPER{} explicitly. \ref{getterInvocation}: Explicitly described getter invocations on \SUPER{}. \subsubsection{Changes Since Version 0.50} % there was no public 0.50! \ref{variables}: Final variables introduce setters that trap on execution. Not initializing a final is a warning, not an error. Initializing a final variable declared with an initializer is a warning, not an error. \ref{requiredFormals}: Initializing formals can specify function types. These may not specify defaults. \ref{instanceMethods}: Corrected override rules to fit with earlier relaxation of function subtype rules. Furthermore, bad overrides provoke warnings not errors. Also, methods and corresponding setters yield warnings. \ref{generativeConstructors}: Initializing a final variable declared with an initializer is a warning, not an error. \ref{staticMethods}: Corresponding setters yield warnings. \ref{inheritanceAndOverriding}: Refined definitions of inheritance and overriding to correctly account for library privacy. \ref{superinterfaces}: Suppress type warnings for unimplemented members of superinterfaces if the class declares \code{noSuchMethod()}. \ref{interfaceInheritanceAndOverriding}: Refined definitions of inheritance and overriding to correctly account for library privacy. \ref{constants}: Literal symbols are constants. \ref{numbers}, \ref{booleans}, \ref{strings}: Specified the runtime type of numbers, booleans and strings. \ref{strings}: Implicit concatenation works among all kinds of strings. \ref{symbols}: Added literal symbols. \ref{if}, \ref{for}, \ref{while}, \ref{do}: Single statements in control constructs implicitly introduce a block. \ref{imports}: Introduced special treatment for imports conflicts with \code{dart:core}. Ambiguous names are treated as malformed types or \code{NoSuchMethodError}s. \ref{typedef}: Tightened restrictions on recursive typedefs. %\ref{typeDynamic}: Clarified that \DYNAMIC{} is not an expression. \subsubsection{Changes Since Version 0.51} \ref{classes}: Mixin applications are a kind of class definition. \ref{generativeConstructors}: Clarify that executing repeated initialization of a final variable by an initializer or initializing formal is a run-time error. \ref{mixins}: Mixin applications are defined using \CLASS{} rather than \TYPEDEF{}. \ref{objectIdentity}: Refined definition of \code{identical()}. \ref{propertyExtraction}: Abstract methods are ignored for purposes of property extraction. \ref{bindingActualsToFormals}: Mismatched arguments lead to \cd{NoSuchMethodError}. \ref{ordinaryInvocation}, \ref{superInvocation}: Correctly account for calls to \cd{noSuchMethod} due to mismatched arguments. \ref{imports}, \ref{exports}: Provenance of declarations allowed to disambiguate imports and exports. \ref{typedef}: Mixin applications are no longer defined via a \TYPEDEF{}. \ref{functionTypes}: All functions must implement \CALL{}. \ref{comments}: Doc comments details are unspecified. \subsubsection{Changes Since Version 0.6} \ref{variables}: Type promotion support added. \ref{formalParameters}: refined scope rules. \ref{classes}: Banned name clashes between type variables and members etc. \ref{factories}: Banned default values in redirecting factories. \ref{constants}: Added constant conditional expressions. \ref{strings}: Allow adjacent single and multiline strings to concatenate. Allow escaped newlines in multiline strings. \ref{const}: Allow parameterized types in const instance creation. \ref{conditional}: Type promotion support added. \ref{logicalBooleanExpressions}: Type promotion support added. \ref{logicalBooleanExpressions} - \ref{bitwiseExpressions}, \ref{operatorPrecedence}: Increased precedence of bitwise operations to be higher than equality and relational expressions. \ref{identifierReference}: Clarified static type rules. Type promotion support added. \ref{typeTest}: Type promotion support added. \ref{if}: Type promotion support added. \ref{try}: \ON{} with no \CATCH{} implies \DYNAMIC{}, not \cd{Object}. \ref{return}: Added warning if \RETURN{} without expression mixed with \RETURN{} with an expression. \ref{exports}: Ensure that exports treat \code{dart:} libs specially, like imports do. \ref{typePromotion}: Added notion of type promotion. \ref{typedef}: Banned all recursion in typedefs. \subsubsection{Changes Since Version 0.7} \ref{new}: Instantiating subclasses of malbounded types is a dynamic error. \ref{leastUpperBounds}: Extended LUBs to all types. \section{Notation} \label{notation} We distinguish between normative and non-normative text. Normative text defines the rules of Dart. It is given in this font. At this time, non-normative text includes: \begin{itemize} \item[Rationale] Discussion of the motivation for language design decisions appears in italics. \rationale{Distinguishing normative from non-normative helps clarify what part of the text is binding and what part is merely expository.} \item[Commentary] Comments such as \commentary{The careful reader will have noticed that the name Dart has four characters}'' serve to illustrate or clarify the specification, but are redundant with the normative text. \commentary{The difference between commentary and rationale can be subtle.} \rationale{ Commentary is more general than rationale, and may include illustrative examples or clarifications. } \item[Open questions] (\Q{in this font}). Open questions are points that are unsettled in the mind of the author(s) of the specification; expect them (the questions, not the authors; precision is important in a specification) to be eliminated in the final specification. \Q{Should the text at the end of the previous bullet be rationale or commentary?} \end{itemize} Reserved words and built-in identifiers (\ref{identifierReference}) appear in {\bf bold}. \commentary{ Examples would be \SWITCH{} or \CLASS{}. } Grammar productions are given in a common variant of EBNF. The left hand side of a production ends with a colon. On the right hand side, alternation is represented by vertical bars, and sequencing by spacing. As in PEGs, alternation gives priority to the left. Optional elements of a production are suffixed by a question mark like so: \code{anElephant?}. Appending a star to an element of a production means it may be repeated zero or more times. Appending a plus sign to a production means it occurs one or more times. Parentheses are used for grouping. Negation is represented by prefixing an element of a production with a tilde. Negation is similar to the not combinator of PEGs, but it consumes input if it matches. In the context of a lexical production it consumes a single character if there is one; otherwise, a single token if there is one. \commentary{ An example would be:} \begin{grammar} {\sf {\bf AProduction:}AnAlternative; AnotherAlternative; OneThing After Another; ZeroOrMoreThings*; OneOrMoreThings+; AnOptionalThing?; (Some Grouped Things); \~{}NotAThing; A\_LEXICAL\_THING . } \end{grammar} % need a match anything or a production that does that, so we can correct bugs wrt use % ~. ~ does not actually parse stuff - it just looks ahead and checks. To get the effect of % parsing anything but X, one needs ~X ANYTHING, not just ~X. There are bugs in the % grammar related to this. % The alternative is to define ~X as anything but X, or to introduce an anthingBut(X) % combinator, such as !X Both syntactic and lexical productions are represented this way. Lexical productions are distinguished by their names. The names of lexical productions consist exclusively of upper case characters and underscores. As always, within grammatical productions, whitespace and comments between elements of the production are implicitly ignored unless stated otherwise. Punctuation tokens appear in quotes. Productions are embedded, as much as possible, in the discussion of the constructs they represent. A list $x_1, \ldots, x_n$ denotes any list of $n$ elements of the form $x_i, 1 \le i \le n$. Note that $n$ may be zero, in which case the list is empty. We use such lists extensively throughout this specification. The notation $[x_1, \ldots, x_n/y_1, \ldots, y_n]E$ denotes a copy of $E$ in which all occurrences of $y_i, 1 \le i \le n$ have been replaced with $x_i$. We sometimes abuse list or map literal syntax, writing $[o_1, \ldots, o_n]$ (respectively $\{k_1: o_1, \ldots, k_n: o_n\}$) where the $o_i$ and $k_i$ may be objects rather than expressions. The intent is to denote a list (respectively map) object whose elements are the $o_i$ (respectively, whose keys are the $k_i$ and values are the $o_i$). The specifications of operators often involve statements such as $x$ $op$ $y$ is equivalent to the method invocation $x.op(y)$. Such specifications should be understood as a shorthand for: \begin{itemize} \item $x$ $op$ $y$ is equivalent to the method invocation $x.op^\prime(y)$, assuming the class of $x$ actually declared a non-operator method named $op^\prime$ defining the same function as the operator $op$. \end{itemize} \rationale{This circumlocution is required because x.op(y), where op is an operator, is not legal syntax. However, it is painfully verbose, and we prefer to state this rule once here, and use a concise and clear notation across the specification. } When the specification refers to the order given in the program, it means the order of the program source code text, scanning left-to-right and top-to-bottom. References to otherwise unspecified names of program entities (such as classes or functions) are interpreted as the names of members of the Dart core library. \commentary{ Examples would be the classes \code{Object} and \code{Type} representing the root of the class hierarchy and the reification of runtime types respectively. } \section{Overview} \label{overview} Dart is a class-based, single-inheritance, pure object-oriented programming language. Dart is optionally typed (\ref{types}) and supports reified generics. The run-time type of every object is represented as an instance of class \code{Type} which can be obtained by calling the getter \code{runtimeType} declared in class \code{Object}, the root of the Dart class hierarchy. Dart programs may be statically checked. The static checker will report some violations of the type rules, but such violations do not abort compilation or preclude execution. Dart programs may be executed in one of two modes: production mode or checked mode. In production mode, static type annotations (\ref{staticTypes}) have absolutely no effect on execution with the exception of reflection and structural type tests. \commentary{ Reflection, by definition, examines the program structure. If we provide reflective access to the type of a declaration, or to source code, it will inevitably produce results that depend on the types used in the underlying code. Type tests also examine the types in a program explicitly. Nevertheless, in most cases, these will not depend on type annotations. The exceptions to this rule are type tests involving function types. Function types are structural, and so depend on the types declared for their parameters and on their return types. } In checked mode, assignments are dynamically checked, and certain violations of the type system raise exceptions at run time. \commentary{ The coexistence between optional typing and reification is based on the following: \begin{enumerate} \item Reified type information reflects the types of objects at runtime and may always be queried by dynamic typechecking constructs (the analogs of instanceOf, casts, typecase etc. in other languages). Reified type information includes class declarations, the runtime type (aka class) of an object, and type arguments to constructors. \item Static type annotations determine the types of variables and function declarations (including methods and constructors). \item Production mode respects optional typing. Static type annotations do not affect runtime behavior. \item Checked mode utilizes static type annotations and dynamic type information aggressively yet selectively to provide early error detection during development. \end{enumerate} } Dart programs are organized in a modular fashion into units called {\em libraries} (\ref{librariesAndScripts}). Libraries are units of encapsulation and may be mutually recursive. \commentary{However they are not first class. To get multiple copies of a library running simultaneously, one needs to spawn an isolate. } \subsection{Scoping} \label{scoping} A {\em namespace} is a mapping of identifiers to declarations. Let $NS$ be a namespace. We say that a name $n$ {\em is in }$NS$ if $n$ is a key of $NS$. We say a declaration $d$ {\em is in }$NS$ if a key of $NS$ maps to $d$. A scope $S_0$ induces a namespace $NS_0$ that maps the simple name of each variable, type or function declaration $d$ declared in $S_0$ to $d$. Labels are not included in the induced namespace of a scope; instead they have their own dedicated namespace. \commentary{It is therefore impossible, e.g., to define a class that declares a method and a field with the same name in Dart. Similarly one cannot declare a top-level function with the same name as a library variable or class. } It is a compile-time error if there is more than one entity with the same name declared in the same scope. \commentary{ In some cases, the name of the declaration differs from the identifier used to declare it. Setters have names that are distinct from the corresponding getters because they always have an = automatically added at the end, and unary minus has the special name unary-. } Dart is lexically scoped. Scopes may nest. A name or declaration $d$ is {\em available in scope} $S$ if $d$ is in the namespace induced by $S$ or if $d$ is available in the lexically enclosing scope of $S$. We say that a name or declaration $d$ is {\em in scope} if $d$ is available in the current scope. If a declaration $d$ named $n$ is in the namespace induced by a scope $S$, then $d$ {\em hides} any declaration named $n$ that is available in the lexically enclosing scope of $S$. \commentary { A consequence of these rules is that it is possible to hide a type with a method or variable. Naming conventions usually prevent such abuses. Nevertheless,the following program is legal: } \begin{dartCode} \CLASS{} HighlyStrung \{ String() $=>$ "?"; \} \end{dartCode} Names may be introduced into a scope by declarations within the scope or by other mechanisms such as imports or inheritance. \rationale{ The interaction of lexical scoping and inheritance is a subtle one. Ultimately, the question is whether lexical scoping takes precedence over inheritance or vice versa. Dart chooses the former. Allowing inherited names to take precedence over locally declared names can create unexpected situations as code evolves. Specifically, the behavior of code in a subclass can change without warning if a new name is introduced in a superclass. Consider: } \begin{dartCode} \LIBRARY{} L1; \CLASS{} S \{\} \LIBRARY{} L2; \IMPORT{} L1.dart'; foo() =$>$ 42; \CLASS{} C \EXTENDS{} S\{ bar() =$>$ foo();\} \end{dartCode} \rationale{Now assume a method \code{foo()} is added to \code{S}. } \begin{dartCode} \LIBRARY{} L1; \CLASS{} S \{foo() =$>$ 91;\} \end{dartCode} \rationale{ If inheritance took precedence over the lexical scope, the behavior of \code{C} would change in an unexpected way. Neither the author of \code{S} nor the author of \code{C} are necessarily aware of this. In Dart, if there is a lexically visible method \code{foo()}, it will always be called. Now consider the opposite scenario. We start with a version of \code{S} that contains \code{foo()}, but do not declare \code{foo()} in library \code{L2}. Again, there is a change in behavior - but the author of \code{L2} is the one who introduced the discrepancy that effects their code, and the new code is lexically visible. Both these factors make it more likely that the problem will be detected. These considerations become even more important if one introduces constructs such as nested classes, which might be considered in future versions of the language. Good tooling should of course endeavor to inform programmers of such situations (discretely). For example, an identifier that is both inherited and lexically visible could be highlighted (via underlining or colorization). Better yet, tight integration of source control with language aware tools would detect such changes when they occur. } \subsection{Privacy} \label{privacy} Dart supports two levels of privacy: {\em public} and {\em private}. A declaration is {\em private} iff its name begins with an underscore (the \_ character) otherwise it is {\em public.} A declaration $m$ is {\em accessible to library $L$} if $m$ is declared in $L$ or if $m$ is public. \commentary{ This means private declarations may only be accessed within the library in which they are declared. } Privacy applies only to declarations within a library, not to library declarations themselves. \rationale{ Libraries do not reference each other by name and so the idea of a private library is meaningless. Thus, if the name of a library begins with an underscore, it has no special significance. } \rationale{Privacy is, at this point, a static notion tied to a particular piece of code (a library). It is designed to support software engineering concerns rather than security concerns. Untrusted code should always run in an another isolate. It is possible that libraries will become first class objects and privacy will be a dynamic notion tied to a library instance. Privacy is indicated by the name of a declaration - hence privacy and naming are not orthogonal. This has the advantage that both humans and machines can recognize access to private declarations at the point of use without knowledge of the context from which the declaration is derived.} \subsection{Concurrency} Dart code is always single threaded. There is no shared-state concurrency in Dart. Concurrency is supported via actor-like entities called {\em isolates}. An isolate is a unit of concurrency. It has its own memory and its own thread of control. Isolates communicate by message passing (\ref{sendingMessages}). No state is ever shared between isolates. Isolates are created by spawning (\ref{spawningAnIsolate}). \section{Errors and Warnings} \label{errorsAndWarnings} This specification distinguishes between several kinds of errors. {\em Compile-time errors} are errors that preclude execution. A compile-time error must be reported by a Dart compiler before the erroneous code is executed. \rationale{A Dart implementation has considerable freedom as to when compilation takes place. Modern programming language implementations often interleave compilation and execution, so that compilation of a method may be delayed, e.g., until it is first invoked. Consequently, compile-time errors in a method $m$ may be reported as late as the time of $m$'s first invocation. As a web language, Dart is often loaded directly from source, with no intermediate binary representation. In the interests of rapid loading, Dart implementations may choose to avoid full parsing of method bodies, for example. This can be done by tokenizing the input and checking for balanced curly braces on method body entry. In such an implementation, even syntax errors will be detected only when the method needs to be executed, at which time it will be compiled (JITed). In a development environment a compiler should of course report compilation errors eagerly so as to best serve the programmer. } If an uncaught compile-time error occurs within the code of a running isolate $A$, $A$ is immediately suspended. The only circumstance where a compile-time error could be caught would be via code run reflectively, where the mirror system can catch it. \rationale{Typically, once a compile-time error is thrown and $A$ is suspended, $A$ will then be terminated. However, this depends on the overall environment. A Dart engine runs in the context of an {\em embedder}, a program that interfaces between the engine and the surrounding computing environment. The embedder will often be a web browser, but need not be; it may be a C++ program on the server for example. When an isolate fails with a compile-time error as described above, control returns to the embedder, along with an exception describing the problem. This is necessary so that the embedder can clean up resources etc. It is then the embedder's decision whether to terminate the isolate or not. } {\em Static warnings} are those errors reported by the static checker. They have no effect on execution. Many, but not all, static warnings relate to types, in which case they are known as {\em static type warnings.} Static warnings must be provided by Dart compilers used during development such as those incorporated in IDEs or otherwise intended to be used by developers for developing code. Compilers that are part of runtime execution environments such as virtual machines should not issue static warnings. {\em Dynamic type errors} are type errors reported in checked mode. {\em Run-time errors} are exceptions raised during execution. Whenever we say that an exception $ex$ is {\em raised} or {\em thrown}, we mean that a throw expression (\ref{throw}) of the form: \code{\THROW{} $ex$;} was implicitly evaluated or that a rethrow statement (\ref{rethrow}) of the form \code{\RETHROW} was executed. When we say that {\em a} $C$ {\em is thrown}, where $C$ is a class, we mean that an instance of class $C$ is thrown. If an uncaught exception is thrown by a running isolate $A$, $A$ is immediately suspended. \section{Variables} \label{variables} Variables are storage locations in memory. \begin{grammar} {\bf variableDeclaration:} declaredIdentifier (,' identifier)* . {\bf declaredIdentifier:} metadata finalConstVarOrType identifier . {\bf finalConstVarOrType:}\FINAL{} type?; \CONST{} type?; varOrType . {\bf varOrType:}\VAR{}; type . {\bf initializedVariableDeclaration:} declaredIdentifier (=' expression)? (,' initializedIdentifier)* % could do top level here . {\bf initializedIdentifier:} identifier (=' expression)? % could do top-level here . {\bf initializedIdentifierList:} initializedIdentifier (,' initializedIdentifier)* . \end{grammar} A variable that has not been initialized has the initial value \NULL{} (\ref{null}). A variable declared at the top-level of a library is referred to as either a {\em library variable} or simply a top-level variable. A {\em static variable} is a variable that is not associated with a particular instance, but rather with an entire library or class. Static variables include library variables and class variables. Class variables are variables whose declaration is immediately nested inside a class declaration and includes the modifier \STATIC{}. A library variable is implicitly static. It is a compile-time error to preface a top-level variable declaration with the built-in identifier (\ref{identifierReference}) \STATIC{}. Static variable declarations are initialized lazily. When a static variable $v$ is read, iff it has not yet been assigned, it is set to the result of evaluating its initializer. The precise rules are given in section \ref{evaluationOfImplicitVariableGetters}. \rationale{The lazy semantics are given because we do not want a language where one tends to define expensive initialization computations, causing long application startup times. This is especially crucial for Dart, which must support the coding of client applications. } A {\em final variable} is a variable whose binding is fixed upon initialization; a final variable $v$ will always refer to the same object after $v$ has been initialized. The declaration of a final variable must include the modifier \FINAL{}. It is a static warning if a final instance variable that has been initialized at its point of declaration is also initialized in a constructor. % It is a static warning if a final instance variable that has been initialized by means of an initializing formal of a constructor is also initialized elsewhere in the same constructor. It is a compile-time error if a local variable $v$ is final and $v$ is not initialized at its point of declaration. \commentary{ A library or static variable is guaranteed to have an initializer at its declaration by the grammar. Attempting to assign to a final variable anywhere except in its declaration or in a constructor header will cause a runtime error to be thrown as discussed below. The assignment will also give rise to a static warning. Any repeated assignment to a final variable will also lead to a runtime error. Taken as a whole, the rules ensure that any attempt to execute multiple assignments to a final variable will yield static warnings and repeated assignments will fail dynamically. } A {\em constant variable} is a variable whose declaration includes the modifier \CONST{}. A constant variable is always implicitly final. A constant variable must be initialized to a compile-time constant (\ref{constants}) or a compile-time error occurs. We say that a variable $v$ is {\em potentially mutated} in some scope $s$ if $v$ is not final or constant and an assignment to $v$ occurs in $s$. If a variable declaration does not explicitly specify a type, the type of the declared variable(s) is \DYNAMIC{}, the unknown type (\ref{typeDynamic}). Static and instance variable declarations always induce implicit getters and setters. The scope into which the implicit getters and setters are introduced depends on the kind of variable declaration involved. A library variable introduces a getter and a setter into the top level scope of the enclosing library. A static class variable introduces a static getter and a static setter into the immediately enclosing class. An instance variable introduces an instance getter and an instance setter into the immediately enclosing class. Local variables are added to the innermost enclosing scope. They do not induce getters and setters. A local variable may only be referenced at a source code location that is after its initializer, if any, is complete, or a compile-time error occurs. The error may be reported either at the point where the premature reference occurs, or at the variable declaration. \rationale { We allow the error to be reported at the declaration to allow implementations to avoid an extra processing phase. } \commentary{ The example below illustrates the expected behavior. A variable $x$ is declared at the library level, and another $x$ is declared inside the function $f$. } \begin{dartCode} \VAR{} x = 0; f(y) \{ \VAR{} z = x; // compile-time error if (y) \{ x = x + 1; // two compile time errors print(x); // compile time error \} \VAR{} x = x++; // compile time error print(x); \} \end{dartCode} \commentary{ The declaration inside $f$ hides the enclosing one. So all references to $x$ inside $f$ refer to the inner declaration of $x$. However, many of these references are illegal, because they appear before the declaration. The assignment to $z$ is one such case. The assignment to $x$ in the \IF{} statement suffers from multiple problems. The right hand side reads $x$ before its declaration, and the left hand side assigns to $x$ before its declaration. Each of these are, independently, compile time errors. The print statement inside the \IF{} is also illegal. The inner declaration of $x$ is itself erroneous because its right hand side attempts to read $x$ before the declaration has terminated. The left hand side is not, technically, a reference or an assignment but a declaration and so is legal. The last print statement is perfectly legal as well. } \commentary { As another example \code{\VAR{} x = 3, y = x;} is legal, because \code{x} is referenced after its initializer. A particularly perverse example involves a local variable name shadowing a type. This is possible because Dart has a single namespace for types, functions and variables. } \begin{dartCode} \CLASS{} C \{\} perverse() \{ \VAR{} v = \NEW{} C(); // compile-time error C aC; // compile-time error \VAR{} C = 10; \} \commentary { Inside \cd{perverse()}, \cd{C} denotes a local variable. The type \cd{C} is hidden by the variable of the same name. The attempt to instantiate \cd{C} causes a compile-time error because it references a local variable prior to its declaration. Similarly, for the declaration of \cd{aC} (even though it is only a type annotation). } \rationale{ As a rule, type annotations are ignored in production mode. However, we do not want to allow programs to compile legally in one mode and not another, and in this extremely odd situation, that consideration takes precedence. } \end{dartCode} % the grammar does not support local getters and setters. The local var discussion does not seem to mention getters and setters based semantics. It simply discusses the creation of the variable, not its access. Access is either assignment or identifiers. Identifiers ignore the getter story. The following rules apply to all static and instance variables. A variable declaration of one of the forms \code{$T$ $v$;}, \code{$T$ $v$ = $e$;} , \code{\CONST{} $T$ $v$ = $e$;}, \code{\FINAL{} $T$ $v$;} or \code{\FINAL{} $T$ $v$ = $e$;} always induces an implicit getter function (\ref{getters}) with signature $T$ \GET{} $v$ whose invocation evaluates as described below (\ref{evaluationOfImplicitVariableGetters}). A variable declaration of one of the forms \code{\VAR{} $v$;}, \code{\VAR{} $v$ = $e$;} , \code{\CONST{} $v$ = $e$;}, \code{\FINAL{} $v$;} or \code{\FINAL{} $v$ = $e$;} always induces an implicit getter function with signature \GET{} $v$ whose invocation evaluates as described below (\ref{evaluationOfImplicitVariableGetters}). A non-final variable declaration of the form \code{{} $T$ $v$;} or the form \code{$T$ $v$ = $e$;} always induces an implicit setter function (\ref{setters}) with signature \VOID{} \SET{} $v=(T$ $x)$ whose execution sets the value of $v$ to the incoming argument $x$. A non-final variable declaration of the form \code{\VAR{} $v$;} or the form \code{\VAR{} $v$ = $e$;} always induces an implicit setter function with signature \SET{} $v=(x)$ whose execution sets the value of $v$ to the incoming argument $x$. % A final variable introduces a setter that throws and causes a type warning A final or constant variable declaration of the form \code{\FINAL{} $T$ $v$;}, \code{\FINAL{} $T$ $v$ = $e$;} or the form \code{\CONST{} $T$ $v$ = $e$;} always induces an implicit setter function (\ref{setters}) with signature \VOID{} \SET{} $v=(T$ $x)$ whose execution causes a runtime exception. It is a static warning to invoke such a setter. A final variable declaration of the form \code{\FINAL{} $v$;}, \code{\FINAL{} $v$ = $e$;} or the form \code{\CONST{} $v$ = $e$;} always induces an implicit setter function with signature \SET{} $v=(x)$ whose execution causes a runtime exception. It is a static warning to invoke such a setter. % maybe redundant with rules for assignment? \rationale{ Creating a setter that may not be used may seem pointless, but it prevents situations where a setter from an enclosing scope might be accidentally accessed from a scope that defines an immutable variable. } \subsection{Evaluation of Implicit Variable Getters} \label{evaluationOfImplicitVariableGetters} Let $d$ be the declaration of a static or instance variable $v$. If $d$ is an instance variable, then the invocation of the implicit getter of $v$ evaluates to the value stored in $v$. If $d$ is a static or library variable then the implicit getter method of $v$ executes as follows: \begin{itemize} \item {\bf Non-constant variable declaration with initializer}. If $d$ is of one of the forms \code{\VAR{} $v$ = $e$;} , \code{$T$ $v$ = $e$;} , \code{\FINAL{} $v$ = $e$;} , \code{\FINAL{} $T$ $v$ = $e$;}, \code{\STATIC{} $v$ = $e$; }, \code{\STATIC{} $T$ $v$ = $e$; }, \code{\STATIC{} \FINAL{} $v$ = $e$; } or \code{\STATIC{} \FINAL{} $T$ $v$ = $e$;} and no value has yet been stored into $v$ then the initializer expression $e$ is evaluated. If, during the evaluation of $e$, the getter for $v$ is invoked, a \code{CyclicInitializationError} is thrown. If the evaluation succeeded yielding an object $o$, let $r = o$, otherwise let $r = \NULL{}$. In any case, $r$ is stored into $v$. The result of executing the getter is $r$. \item {\bf Constant variable declaration}. If $d$ is of one of the forms \code{\CONST{} $v$ = $e$; } , \code{\CONST{} $T$ $v$ = $e$; }, \code{\STATIC{} \CONST{} $v$ = $e$; } or \code{\STATIC{} \CONST{} $T$ $v$ = $e$;} the result of the getter is the value of the compile time constant $e$. \commentary{Note that a compile time constant cannot depend on itself, so no cyclic references can occur.} Otherwise \item {\bf Variable declaration without initializer}. The result of executing the getter method is the value stored in $v$. \end{itemize} \section{Functions} \label{functions} Functions abstract over executable actions. \begin{grammar} {\bf functionSignature:} metadata returnType? identifier formalParameterList . {\bf returnType:} \VOID{}; type . {\bf functionBody:}={\escapegrammar \gt}' expression {\escapegrammar ;}'; block . {\bf block:} \{' statements \}' . \end{grammar} 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}). 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: \begin{itemize} \item A block statement (\ref{blocks}) containing the statements (\ref{statements}) executed by the function. In this case, if the last statement of a function is not a return statement, the statement \code{\RETURN{};} is implicitly appended to the function body. \rationale{ 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 \NULL{}. See further discussion in section \ref{return}. } OR \item of the form \code{=$>$ $e$} which is equivalent to a body of the form \code{\{\RETURN{} $e$;\}}. \end{itemize} % A function has a formal parameter scope and a body scope. The enclosing scope of a function's body scope is its formal parameter scope. The enclosing scope of the formal parameter scope of a function is the enclosing scope of the function. % The body of a function $f$ is processed within the body scope of $f$. %\rationale{This may seem obvious, but needs to be stated.} % \commentary{It follows from the above rules that the formal parameters of a function may be referenced within its body. } \subsection{Function Declarations} \label{functionDeclarations} A {\em function declaration} is a function that is neither a member of a class nor a function literal. Function declarations include {\em library functions}, which are function declarations %(including getters and setters) at the top level of a library, and {\em local functions}, which are function declarations declared inside other functions. Library functions are often referred to simply as top-level functions. A function declaration consists of an identifier indicating the function's name, possibly prefaced by a return type. The function name is followed by a signature and body. For getters, the signature is empty. The body is empty for functions that are external. The scope of a library function is the scope of the enclosing library. The scope of a local function is described in section \ref{localFunctionDeclaration}. In both cases, the name of the function is in scope in its formal parameter scope (\ref{formalParameters}). %A function declaration of the form $T_0$ $id(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])\{s\}$ is equivalent to a variable declaration of the form \code{\FINAL{} $F$ $id$ = $(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])\{s\}$}, where $F$ is the function type alias (\ref{typedef}) \code{\TYPEDEF{} $T_0$ $F(T_1$ $a_1, \ldots, T_n$ $a_n, [T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}])$}. Likewise, a function declaration of the form $id(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])\{s\}$ is equivalent to a variable declaration of the form \code{\FINAL{} $F$ $id$ = $(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])\{s\}$}, where $F$ is the function type alias \code{\TYPEDEF{} $F(T_1$ $a_1, \ldots, T_n$ $a_n, [T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}])$}. %\Q{We need to cover library getters as well.} %\Q{ The definition in terms of variables is untrue, because the code would be illegal. The initializer cannot refer to the function name in this case. I believe the best fix is to relax this %requirement in the case of closures. See bug 315. %} %\commentary{ %Some obvious conclusions: %A function declaration of the form $id(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$ is equivalent to a variable declaration of the form \code{\FINAL{} $id$ = ($(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$}. %A function literal of the form $(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$ is equivalent to a function literal of the form \code{$(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])\{$ \RETURN{} $e$;\}}. %} %A function declaration of the form $T_0$ $id(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\})\{s\}$ is equivalent to a variable declaration of the form \code{\FINAL{} $F$ $id$ = $(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\})\{s\}$}, where $F$ is the function type alias (\ref{typedef}) \code{\TYPEDEF{} $T_0$ $F(T_1$ $a_1, \ldots, T_n$ $a_n, \{T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}]\}$}. Likewise, a function declaration of the form $id(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\})\{s\}$ is equivalent to a variable declaration of the form \code{\FINAL{} $F$ $id$ = $(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\})\{s\}$}, where $F$ is the function type alias \code{\TYPEDEF{} $F(T_1$ $a_1, \ldots, T_n$ $a_n, \{T_{n+1}$ $x_{n+1}, \ldots, T_{n+k}$ $x_{n+k}\})$}. It is a compile-time error to preface a function declaration with the built-in identifier \STATIC{}. \subsection{Formal Parameters} \label{formalParameters} 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. The formal parameter list of a function introduces a new scope known as the functions {\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 body of a function introduces a new scope known as the functions {\em body scope}. The body scope of a function $f$ is enclosed in the scope introduced by the formal parameter scope of $f$. %The formal parameter scope of a function maps the name of each formal parameter $p$ to the value $p$ is bound to. % The formal parameters of a function are processed in the enclosing scope of the function. % \commentary{this means that the parameters themselves may not be referenced within the formal parameter list.} It is a compile-time error if a formal parameter is declared as a constant variable (\ref{variables}). \begin{grammar} {\bf formalParameterList:}(' )'; (' normalFormalParameters ( ,' optionalFormalParameters)? )'; (' optionalFormalParameters )' . %\end{grammar} %} %\begin{grammar} %formalParameterList: % '(' restFormalParameter? ')'; % '(' namedFormalParameters ')'; % '(' normalFormalParameters normalFormalParameterTail? ')' % . {\bf normalFormalParameters:} normalFormalParameter (,' normalFormalParameter)* . {\bf optionalFormalParameters:}optionalPositionalFormalParameters; namedFormalParameters . {\bf optionalPositionalFormalParameters:} [' defaultFormalParameter (,' defaultFormalParameter)* ]' . {\bf namedFormalParameters:} \{' defaultNamedParameter (,' defaultNamedParameter)* \}' . \end{grammar} %Formal parameters are always \FINAL{}. %\Q{We're awaiting some data on whether enforcing this would cause widespread pain.} %A formal parameter is always considered to be initialized. \rationale{This is because it will always be initialized by the call - even if it is optional.} \subsubsection{Required Formals} \label{requiredFormals} A {\em required formal parameter} may be specified in one of three ways: \begin{itemize} \item By means of a function signature that names the parameter and describes its type as a function type (\ref{functionTypes}). It is a compile-time error if any default values are specified in the signature of such a function type.% explain what the type is in this case? Where is this described in general? \item As an initializing formal, which is only valid as a parameter to a generative constructor (\ref{generativeConstructors}). % do we need to say this, or anything more? \item Via an ordinary variable declaration (\ref{variables}). \end{itemize} \begin{grammar} {\bf normalFormalParameter:}functionSignature; fieldFormalParameter; simpleFormalParameter . {\bf simpleFormalParameter:}declaredIdentifier; metadata identifier . {\bf fieldFormalParameter:} metadata finalConstVarOrType? \THIS{} {\escapegrammar .}' identifier formalParameterList? . \end{grammar} %\subsubsection{Rest Formals} %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[]$. %\begin{grammar} %restFormalParameter: % finalConstVarOrType? '{\escapegrammar ...}' identifier %\end{grammar} \subsubsection{Optional Formals} \label{optionalFormals} Optional parameters may be specified and provided with default values. \begin{grammar} {\bf defaultFormalParameter:} normalFormalParameter ('=' expression)? . {\bf defaultNamedParameter:} normalFormalParameter ( {\escapegrammar :}' expression)? . \end{grammar} It is a compile-time error if the default value of an optional parameter is not a compile-time constant (\ref{constants}). If no default is explicitly specified for an optional parameter an implicit default of \NULL{} is provided. It is a compile-time error if the name of a named optional parameter begins with an \_' character. \rationale{ The need for this restriction is a direct consequence of the fact that naming and privacy are not orthogonal. If we allowed named parameters to begin with an underscore, they would be considered private and inaccessible to callers from outside the library where it was defined. If a method outside the library overrode a method with a private optional name, it would not be a subtype of the original method. The static checker would of course flag such situations, but the consequence would be that adding a private named formal would break clients outside the library in a way they could not easily correct. } \subsection{Type of a Function} \label{typeOfAFunction} If a function does not declare a return type explicitly, its return type is \DYNAMIC{} (\ref{typeDynamic}). 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$. 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}, \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$. 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$. The run time type of a function object always implements the class \cd{Function}. \commentary{ One cannot assume, based on the above, that given a function \cd{f}, \cd{f.runtimeType} will actually be \cd{Function}, or that any two distinct function objects necessarily have the same runtime type. } \rationale{ It is up to the implementation to choose an appropriate representation for functions. For example, consider that a closure produced via property extraction treats equality different from ordinary closures, and is therefore likely a different class. Implementations may also use different classes for functions based on arity and or type. Arity may be implicitly affected by whether a function is an instance method (with an implicit receiver parameter) or not. The variations are manifold, and so this specification only guarantees that function objects are instances of some class that is considered to implement \cd{Function}. } \subsection{External Functions} \label{externalFunctions} An {\em external function} is a function whose body is provided separately from its declaration. An external function may be a top-level function (\ref{librariesAndScripts}), a method (\ref{instanceMethods}, \ref{staticMethods}), a getter (\ref{getters}), a setter (\ref{setters}) or a non-redirecting constructor (\ref{generativeConstructors}, \ref{factories}). External functions are introduced via the built-in identifier \EXTERNAL{} (\ref{identifierReference}) followed by the function signature. \rationale{ External functions allow us to introduce type information for code that is not statically known to the Dart compiler. } \commentary{ Examples of external functions might be foreign functions (defined in C, or Javascript etc.), primitives of the implementation (as defined by the Dart runtime), or code that was dynamically generated but whose interface is statically known. However, an abstract method is different from an external function, as it has {\em no} body. } An external function is connected to its body by an implementation specific mechanism. Attempting to invoke an external function that has not been connected to its body will raise a \code{NoSuchMethodError} or some subclass thereof. The actual syntax is given in sections \ref{classes} and \ref{librariesAndScripts} below. \section{Classes} \label{classes} A {\em class} defines the form and behavior of a set of objects which are its {\em instances}. Classes may be defined by class declarations as described below, or via mixin applications (\ref{mixinApplication}). \begin{grammar} {\bf classDefinition:} metadata \ABSTRACT{}? \CLASS{} identifier typeParameters? (superclass mixins?)? interfaces? \\ \{' (metadata classMemberDefinition)* \}'; metadata \ABSTRACT{}? \CLASS{} mixinApplicationClass . {\bf mixins:} \WITH{} typeList . {\bf classMemberDefinition:}declaration {\escapegrammar ;}' ; methodSignature functionBody . {\bf methodSignature:}constructorSignature initializers?; factoryConstructorSignature; \STATIC{}? functionSignature; \STATIC{}? getterSignature; \STATIC{}? setterSignature; operatorSignature . {\bf declaration:}constantConstructorSignature (redirection $|$ initializers)?; constructorSignature (redirection $|$ initializers)?; \EXTERNAL{} constantConstructorSignature; \EXTERNAL{} constructorSignature; ((\EXTERNAL{} \STATIC{} ?))? getterSignature; ((\EXTERNAL{} \STATIC{}?))? setterSignature; \EXTERNAL{}? operatorSignature; ((\EXTERNAL{} \STATIC{}?))? functionSignature; \STATIC{} (\FINAL{} $|$ \CONST{}) type? staticFinalDeclarationList; \CONST{} type? staticFinalDeclarationList; \FINAL{} type? initializedIdentifierList; \STATIC{}? (\VAR{} $|$ type) initializedIdentifierList . {\bf staticFinalDeclarationList:} staticFinalDeclaration (,' staticFinalDeclaration)* . {\bf staticFinalDeclaration:} identifier =' expression . \end{grammar} A class has constructors, instance members and static members. The instance members of a class are its instance methods, getters, setters and instance variables. The static members of a class are its static methods, getters, setters and static variables. The members of a class are its static and instance members. % A class has a static scope and an instance scope. The enclosing scope of the static scope of a non-generic class is the enclosing scope of the class declaration. The enclosing scope of the static scope of a generic class is the type parameter scope (\ref{}) of the generic class declaration. %The enclosing scope of a class' instance scope is the class' static scope. %The enclosing scope of an instance member declaration is the instance scope of the class in which it is declared. %The enclosing scope of a static member declaration is the static scope of the class in which it is declared. Every class has a single superclass except class \code{Object} which has no superclass. A class may implement a number of interfaces %, either by declaring them in its implements clause (\ref{superinterfaces}). % or via interface injection declarations (\ref{interfaceInjection}) outside the class declaration An {\em abstract class} is %either a class that is explicitly declared with the \ABSTRACT{} modifier, either by means of a class declaration or via a type alias (\ref{typedef}) for a mixin application (\ref{mixinApplication}). A {\em concrete class} is a class that is not abstract. %, or a class that declares at least one abstract method (\ref{abstractInstanceMembers}). \rationale{ %The abstract modifier for classes is intended to be used in scenarios where an abstract class $A$ inherits from another abstract class $B$. In such a situation, it may be that Aitself does not declare any abstract methods. In the absence of an abstract modifier on the class, the class would be interpreted as a concrete class. However, w We want different behavior for concrete classes and abstract classes. If $A$ is intended to be abstract, we want the static checker to warn about any attempt to instantiate $A$, and we do not want the checker to complain about unimplemented methods in $A$. In contrast, if $A$ is intended to be concrete, the checker should warn about all unimplemented methods, but allow clients to instantiate it freely. } The {\em interface of class $C$} is an implicit interface that declares instance members that correspond to the instance members declared by $C$, and whose direct superinterfaces are the direct superinterfaces of $C$ (\ref{superinterfaces}). When a class name appears as a type, that name denotes the interface of the class. % making an exception for the setters generated for final fields is tempting but problematic. % If a super type defines a setter, it will be overridden yet have no impact on the interface. % Maybe the final field hides the setter in scope? % I think the original rules were best. It is a compile-time error if a class declares two members of the same name. %, except that a getter and a setter may be declared with the same name provided both are instance members or both are static members. It is a compile-time error if a class has an instance member and a static member with the same name. % It is a compile-time error if a generic (\ref{generics}) class declares a member with the same name as one of its type parameters. \commentary{Here are simple examples, that illustrate the difference between has a member'' and declares a member''. For example, \code{B} {\em declares} one member named \code{f}, but {\em has} two such members. The rules of inheritance determine what members a class has. } \begin{dartCode} \CLASS{} A \{ \VAR{} i = 0; \VAR{} j; f(x) =$>$ 3; \} \CLASS{} B \EXTENDS{} A \{ int i = 1; // getter i and setter i= override versions from A \STATIC{} j; // compile-time error: static getter \& setter conflict with //instance getter \& setter /* compile-time error: static method conflicts with instance method */ \STATIC{} f(x) =$>$ 3; \} \end{dartCode} It is a compile time error if a class $C$ declares a member with the same name as $C$. It is a compile time error if a generic class declares a type variable with the same name as the class or any of its members or constructors. \subsection{Instance Methods} \label{instanceMethods} Instance methods are functions (\ref{functions}) whose declarations are immediately contained within a class declaration and that are not declared \STATIC{}. The instance methods of a class $C$ are those instance methods declared by $C$ and the instance methods inherited by $C$ from its superclass. %make these warnings if possible It is a static warning if an instance method $m_1$ overrides (\ref{inheritanceAndOverriding}) an instance member $m_2$ and $m_1$ has a greater number of required parameters than $m_2$. It is a static warning if an instance method $m_1$ overrides an instance member $m_2$ and $m_1$ has fewer positional parameters than $m_2$. It is a static warning if an instance method $m_1$ overrides an instance member $m_2$ and $m_1$ does not declare all the named parameters declared by $m_2$. % not quite right. It should be ok to override a method that requires N parameters with one that requires M < N but accepts the others as optional. It is a static warning if an instance method $m_1$ overrides an instance member $m_2$ and the type of $m_1$ is not a subtype of the type of $m_2$. It is a static warning if an instance method $m_1$ overrides an instance member $m_2$, the signature of $m_2$ explicitly specifies a default value for a formal parameter $p$ and the signature of $m_1$ specifies a different default value for $p$. It is a static warning if a class $C$ declares an instance method named $n$ and has a setter named $n=$. It is a static warning if a class $C$ declares an instance method named $n$ and an accessible static member named $n$ is declared in a superclass of $C$. % Works. If the name is public, no issue. If it's private, if a subclass has a conflicting inst var, it either is in the same lib and will be flagged, or is in another and is not an issue. \subsubsection{Operators} \label{operators} {\em Operators} are instance methods with special names. \begin{grammar} {\bf operatorSignature:} returnType? \OPERATOR{} operator formalParameterList . {\bf operator:}\~{}'; binaryOperator; [' ]' ; [' ]' =' . {\bf binaryOperator:}multiplicativeOperator; additiveOperator; shiftOperator; relationalOperator; =='; bitwiseOperator . \end{grammar} An operator declaration is identified using the built-in identifier (\ref{identifierReference}) \OPERATOR{}. The following names are allowed for user-defined operators: \code{$<$, $>$, $<$=, $>$=, ==, -, +, /, \~{}/, *, \%, $|$, \^{}, \&, $<<$, $>>$, []=, [], \~{}.} It is a compile-time error if the arity of the user-declared operator \code{[]=} is not 2. It is a compile-time error if the arity of a user-declared operator with one of the names: \code{ $<$, $>$, $<$=, $>$=, ==, -, +, \~{}/, /, *, \%, $|$, \^{}, \&, $<<$, $>>$, []} is not 1. It is a compile-time error if the arity of the user-declared operator \code{-} is not 0 or 1. \commentary{ The \code{-} operator is unique in that two overloaded versions are permitted. If the operator has no arguments, it denotes unary minus. If it has an argument, it denotes binary subtraction. } The name of the unary operator \code{-} is \code{unary-}. \rationale{ This device allows the two methods to be distinguished for purposes of method lookup, override and reflection. } It is a compile-time error if the arity of the user-declared operator \code{ \~{}} is not 0. It is a compile-time error to declare an optional parameter in an operator. It is a static warning if the return type of the user-declared operator \code{[]=} is explicitly declared and not \VOID{}. \subsection{Getters} \label{getters} Getters are functions (\ref{functions}) that are used to retrieve the values of object properties. \begin{grammar} {\bf getterSignature:} type? \GET{} identifier . \end{grammar} %\Q{Why does a getter have a formal parameter list at all?} If no return type is specified, the return type of the getter is \DYNAMIC{}. A getter definition that is prefixed with the \STATIC{} modifier defines a static getter. Otherwise, it defines an instance getter. The name of the getter is given by the identifier in the definition. %It is a compile-time error if a getters formal parameter list is not empty. The instance getters of a class $C$ are those instance getters declared by $C$, either implicitly or explicitly, and the instance getters inherited by $C$ from its superclass. The static getters of a class $C$ are those static getters declared by $C$. It is a compile-time error if a class has both a getter and a method with the same name. This restriction holds regardless of whether the getter is defined explicitly or implicitly, or whether the getter or the method are inherited or not. \commentary{ This implies that a getter can never override a method, and a method can never override a getter or field. } It is a static warning if a getter $m_1$ overrides (\ref{inheritanceAndOverriding}) a getter $m_2$ and the type of $m_1$ is not a subtype of the type of $m_2$. It is a static warning if a class declares a static getter named $v$ and also has a non-static setter named $v=$. It is a static warning if a class $C$ declares an instance getter named $v$ and an accessible static member named $v$ or $v=$ is declared in a superclass of $C$. \subsection{Setters} \label{setters} Setters are functions (\ref{functions}) that are used to set the values of object properties. % what about top level ones? Same for getters \begin{grammar} {\bf setterSignature:} returnType? \SET{} identifier formalParameterList . \end{grammar} If no return type is specified, the return type of the setter is \DYNAMIC{}. A setter definition that is prefixed with the \STATIC{} modifier defines a static setter. Otherwise, it defines an instance setter. The name of a setter is obtained by appending the string =' to the identifier given in its signature. \commentary{Hence, a setter name can never conflict with, override or be overridden by a getter or method.} The instance setters of a class $C$ are those instance setters declared by $C$ either implicitly or explicitly, and the instance setters inherited by $C$ from its superclass. The static setters of a class $C$ are those static setters declared by $C$. It is a compile-time error if a setter's formal parameter list does not consist of exactly one required formal parameter $p$. \rationale{We could enforce this via the grammar, but wed have to specify the evaluation rules in that case.} %It is a compile-time error if a class has both a setter and a method with the same name. This restriction holds regardless of whether the setter is defined explicitly or implicitly, or whether the setter or the method are inherited or not. It is a static warning if a setter declares a return type other than \VOID{}. It is a static warning if a setter $m_1$ overrides (\ref{inheritanceAndOverriding}) a setter $m_2$ and the type of $m_1$ is not a subtype of the type of $m_2$. It is a static warning if a class has a setter named $v=$ with argument type $T$ and a getter named $v$ with return type $S$, and $T$ may not be assigned to $S$. It is a static warning if a class declares a static setter named $v=$ and also has a non-static member named $v$. It is a static warning if a class $C$ declares an instance setter named $v=$ and an accessible static member named $v=$ or $v$ is declared in a superclass of $C$. \subsection{Abstract Instance Members} \label{abstractInstanceMembers} An {\em abstract method} (respectively, {\em abstract getter} or {\em abstract setter)} is an instance method, getter or setter that is not declared \EXTERNAL{} and does not provide an implementation. An {\em concrete method} (respectively, {\em concrete getter} or {\em concrete setter)} is an instance method, getter or setter that is not abstract. %The declaration of an abstract method is prefixed by the built-in identifier (\ref{identifierReference}) \ABSTRACT{}. \rationale{ Earlier versions of Dart required that abstract members be identified by prefixing them with the modifier \ABSTRACT{}. The elimination of this requirement is motivated by the desire to use abstract classes as interfaces. Every Dart class induces an implicit interface. Using an abstract class instead of an interface has important advantages. An abstract class can provide default implementations; it can also provide static methods, obviating the need for service classes such as \code{Collections} or \code{Lists}, whose entire purpose is to group utilities related to a given type. Eliminating the requirement for an explicit modifier on members makes abstract classes more concise, making abstract classes an attractive substitute for interface declarations. } \commentary {Invoking an abstract method, getter or setter results in an invocation of \cd{noSuchMethod} exactly as if the declaration did not exist, unless a suitable member $a$ is available in a superclass, in which case $a$ is invoked. The normative specification for this appears under the definitions of lookup for methods, getters and setters. } % so does an abstract method override a method in a superclass or not? Does the superclass method get inherited or not? This generally makes the spec inconsistent, as there is no simple answer. % For example - if we say it does not override, then the superclass member is inherited, in which case the rules for warning break down, and also there is question of whether there are two definitions of the same name. % But if we do override, method lookup rules break down. So several things need revisiting. \rationale{ The purpose of an abstract method is to provide a declaration for purposes such as type checking and reflection. In classes used as mixins, it is often useful to introduce such declarations for methods that the mixin expects will be provided by the superclass the mixin is applied to. } %always results in a run-time error. This must be \code{NoSuchMethodError} or an instance of a subclass of \code{NoSuchMethodError}, such as \code{AbstractMethodError}. It is a static warning if an abstract member is declared or inherited in a concrete class unless that member overrides a concrete one. \rationale { We wish to warn if one declares a concrete class with abstract members. However, code like the following should work without warnings: } \begin{dartCode} class Base \{ int get one =$>$ 1; \} abstract class Mix \{ int get one; int get two =$>$ one + one; \} class C extends Base with Mix \{ \} \} \end{dartCode} \rationale{At run time, the concrete method \cd{one} declared in \cd{Base} will be executed, and no problem should arise. Therefore no warning should be issued and so we suppress warnings if a corresponding concrete member exists in the hierarchy. } \subsection{Instance Variables} \label{instanceVariables} Instance variables are variables whose declarations are immediately contained within a class declaration and that are not declared \STATIC{}. The instance variables of a class $C$ are those instance variables declared by $C$ and the instance variables inherited by $C$ from its superclass. It is a compile-time error if an instance variable is declared to be constant. \rationale{ The notion of a constant instance variable is subtle and confusing to programmers. An instance variable is intended to vary per instance. A constant instance variable would have the same value for all instances, and as such is already a dubious idea. The language could interpret const instance variable declarations as instance getters that return a constant. However, a constant instance variable could not be treated as a true compile time constant, as its getter would be subject to overriding. Given that the value does not depend on the instance, it is better to use a static class variable. An instance getter for it can always be defined manually if desired. } %An instance variable declaration of one of the forms \code{$T$ $v$;}, \code{\FINAL{} $T$ $v$;} , \code{$T$ $v$ = $e$;} , \code{\CONST{} $T$ $v$ = $e$;} or \code{\FINAL{} $T$ $v$ = $e$;} always induces an implicit getter function (\ref{getters}) with signature %$T$ \GET{} $v$ %whose invocation evaluates to the value stored in $v$. %An instance variable declaration of one of the forms \code{\VAR{} $v$;}, \code{\FINAL{} $v$;}, \code{\VAR{} $v$ = $e$;} , \code{\CONST{} $v$ = $e$;} or \code{\FINAL{} $v$ = $e$;} always induces an implicit getter function with signature %\GET{} $v$ %whose invocation evaluates to the value stored in $v$. %\commentary{Getters are introduced for all instance and static variables (\ref{staticVariables}), regardless of whether they are const/final or not.} %A non-final instance variable declaration of the form \code{$T$ $v$;} or the form \code{$T$ $v$ = $e$;} always induces an implicit setter function (\ref{setters}) with signature %\VOID{} \SET{} $v=(T$ $x)$ %whose execution sets the value of $v$ to the incoming argument $x$. %A non-final instance variable declaration of the form \code{\VAR{} $v$;} or the form \code{\VAR{} $v$ = $e$;} always induces an implicit setter function with signature %\SET{} $v=(x)$ %whose execution sets the value of $v$ to the incoming argument $x$. % It is a compile-time error/warning if a class $C$ declares a final instance variable $v$ and $C$ inherits a setter $v=$. \subsection{Constructors} \label{constructors} A {\em constructor} is a special function that is used in instance creation expressions (\ref{instanceCreation}) to produce objects. Constructors may be generative (\ref{generativeConstructors}) or they may be factories (\ref{factories}). A {\em constructor name} always begins with the name of its immediately enclosing class, and may optionally be followed by a dot and an identifier $id$. It is a compile-time error if $id$ is the name of a member declared in the immediately enclosing class. It is a compile-time error if the name of a constructor is not a constructor name. % In what scope do constructors go? The simple names of named constructors go in the static scope of the class. Unnamed ones go nowhere, but we use the class name to refer to them; the class name could also in the static scope of the class as well to prevent weird errors, or we could ban it explicitly and avoiding duplication. Similarly, the instance scope could contain the constructor names and class name, or we could have special rules to prevent collisions between instance members and constructors or the class. % The enclosing scope of a generative constructor is the instance scope of the class in which it is declared (but what about redirecting?) Iff no constructor is specified for a class $C$, it implicitly has a default constructor \code{C() : \SUPER{}() \{\}}, unless $C$ is class \code{Object}. \subsubsection{Generative Constructors} \label{generativeConstructors} A {\em generative constructor} consists of a constructor name, a constructor parameter list, and either a redirect clause or an initializer list and an optional body. \begin{grammar} {\bf constructorSignature:} identifier ({\escapegrammar .}' identifier)? formalParameterList . \end{grammar} A {\em constructor parameter list} is a parenthesized, comma-separated list of formal constructor parameters. A {\em formal constructor parameter} is either a formal parameter (\ref{formalParameters}) or an initializing formal. An {\em initializing formal} has the form \code{\THIS{}.id}, where \code{id} is the name of an instance variable of the immediately enclosing class. It is a compile-time error if an initializing formal is used by a function other than a non-redirecting generative constructor. If an explicit type is attached to the initializing formal, that is its static type. Otherwise, the type of an initializing formal named \code{id} is $T_{id}$, where $T_{id}$ is the type of the field named \code{id} in the immediately enclosing class. It is a static warning if the static type of \code{id} is not assignable to $T_{id}$. Using an initializing formal \code{\THIS{}.id} in a formal parameter list does not introduce a formal parameter name into the scope of the constructor. However, the initializing formal does effect the type of the constructor function exactly as if a formal parameter named \code{id} of the same type were introduced in the same position. Initializing formals are executed during the execution of generative constructors detailed below. Executing an initializing formal \code{\THIS{}.id} causes the field \code{id} of the immediately surrounding class to be assigned the value of the corresponding actual parameter, unless $id$ is a final variable that has already been initialized, in which case a runtime error occurs. \commentary{ The above rule allows initializing formals to be used as optional parameters: } \begin{dartCode} class A \{ int x; A([this.x]); \} \end{dartCode} \commentary{is legal, and has the same effect as} \begin{dartCode} class A \{ int x; A([int x]): this.x = x; \} \end{dartCode} A {\em fresh instance} is an instance whose identity is distinct from any previously allocated instance of its class. A generative constructor always operates on a fresh instance of its immediately enclosing class. \commentary{ The above holds if the constructor is actually run, as it is by \NEW{}. If a constructor $c$ is referenced by \CONST{}, $c$ may not be run; instead, a canonical object may be looked up. See the section on instance creation (\ref{instanceCreation}). } If a generative constructor $c$ is not a redirecting constructor and no body is provided, then $c$ implicitly has an empty body \code{\{\}}. \paragraph{Redirecting Constructors} \label{redirectingConstructors} A generative constructor may be {\em redirecting}, in which case its only action is to invoke another generative constructor. A redirecting constructor has no body; instead, it has a redirect clause that specifies which constructor the invocation is redirected to, and with what arguments. \begin{grammar} {\bf redirection:} {\escapegrammar :}' \THIS{} ({\escapegrammar .}' identifier)? arguments . \end{grammar} % Need to specify exactly how executing a redirecting constructor works %\Q{We now have generative constructors with no bodies as well.} \paragraph{Initializer Lists} An initializer list begins with a colon, and consists of a comma-separated list of individual {\em initializers}. There are two kinds of initializers. \begin{itemize} \item A {\em superinitializer} identifies a {\em superconstructor} - that is, a specific constructor of the superclass. Execution of the superinitializer causes the initializer list of the superconstructor to be executed. \item An {\em instance variable initializer} assigns a value to an individual instance variable. \end{itemize} \begin{grammar} {\bf initializers:} {\escapegrammar :}' superCallOrFieldInitializer (,' superCallOrFieldInitializer)* . {\bf superCallOrFieldInitializer:}\SUPER{} arguments; \SUPER{} {\escapegrammar .}' identifier arguments; fieldInitializer . {\bf fieldInitializer:} (\THIS{} {\escapegrammar .}')? identifier =' conditionalExpression cascadeSection* . \end{grammar} Let $k$ be a generative constructor. Then $k$ may include at most one superinitializer in its initializer list or a compile-time error occurs. If no superinitializer is provided, an implicit superinitializer of the form \SUPER{}() is added at the end of $k$'s initializer list, unless the enclosing class is class \code{Object}. It is a compile-time error if more than one initializer corresponding to a given instance variable appears in $k$'s initializer list. It is a compile-time error if $k$'s initializer list contains an initializer for a variable that is initialized by means of an initializing formal of $k$. % It is a compile-time error if $k$'s initializer list contains an initializer for a final variable $f$ whose declaration includes an initialization expression. Each final instance variable $f$ declared in the immediately enclosing class must have an initializer in $k$'s initializer list unless it has already been initialized by one of the following means: \begin{itemize} \item Initialization at the declaration of $f$. \item Initialization by means of an initializing formal of $k$. \end{itemize} or a static warning occurs. It is a compile-time error if $k$'s initializer list contains an initializer for a variable that is not an instance variable declared in the immediately surrounding class. \commentary{The initializer list may of course contain an initializer for any instance variable declared by the immediately surrounding class, even if it is not final. } It is a compile-time error if a generative constructor of class \code{Object} includes a superinitializer. Execution of a generative constructor $k$ is always done with respect to a set of bindings for its formal parameters and with \THIS{} bound to a fresh instance $i$ and the type parameters of the immediately enclosing class bound to a set of actual type arguments $V_1, \ldots , V_m$. \commentary{These bindings are usually determined by the instance creation expression that invoked the constructor (directly or indirectly). However, they may also be determined by a reflective call,. } If $k$ is redirecting, then its redirect clause has the form \THIS{}$.g(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ where $g$ identifies another generative constructor of the immediately surrounding class. Then execution of $k$ proceeds by evaluating the argument list $(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$, and then executing $g$ with respect to the bindings resulting from the evaluation of $(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$ and with \THIS{} bound to $i$ and the type parameters of the immediately enclosing class bound to $V_1, \ldots , V_m$. Otherwise, execution proceeds as follows: %First, a fresh instance (\ref{generativeConstructors}) $i$ of the immediately enclosing class is allocated. Next, the instance variable declarations of the immediately enclosing class are visited in the order they appear in the program text. For each such declaration $d$, if $d$ has the form \code{$finalConstVarOrType$ $v$ = $e$; } then the instance variable $v$ of $i$ is bound to the value of $e$ (which is necessarily a compile-time constant). %Next, a Any initializing formals declared in $k$'s parameter list are executed in the order they appear in the program text. % In fact, this order is unobservable; this could be done any time prior to running the body, since % these only effect \THIS{}. Then, $k$'s initializers are executed in the order they appear in the program. \rationale {We could observe the order by side effecting external routines called. So we need to specify the order.} After all the initializers have completed, the body of $k$ is executed in a scope where \THIS{} is bound to $i$. Execution of the body begins with execution of the body of the superconstructor with \THIS{} bound to $i$, the type parameters of the immediately enclosing class bound to a set of actual type arguments $V_1, \ldots , V_m$ and the formal parameters bindings determined by the argument list of the superinitializer of $k$. \rationale{ This process ensures that no uninitialized final field is ever seen by code. Note that \THIS{} is not in scope on the right hand side of an initializer (see \ref{this}) so no instance method can execute during initialization: an instance method cannot be directly invoked, nor can \THIS{} be passed into any other code being invoked in the initializer. } Execution of an initializer of the form \code{\THIS{}.$v$ = $e$} proceeds as follows: First, the expression $e$ is evaluated to an object $o$. Then, the instance variable $v$ of the object denoted by \THIS{} is bound to $o$, unless $v$ is a final variable that has already been initialized, in which case a runtime error occurs. In checked mode, it is a dynamic type error if $o$ is not \NULL{} and the interface of the class of $o$ is not a subtype of the actual type of the field $v$. An initializer of the form \code{$v$ = $e$} is equivalent to an initializer of the form \code{\THIS{}.$v$ = $e$}. Execution of a superinitializer of the form \SUPER{}$(a_1, \ldots, a_n, x_{n+1}: a_{n+1}, \ldots, x_{n+k}: a_{n+k})$ (respectively \SUPER{}$.id(a_1, \ldots, a_n, x_{n+1}: a_{n+1}, \ldots, x_{n+k}: a_{n+k})$ proceeds as follows: First, the argument list $(a_1, \ldots, a_n, x_{n+1}: a_{n+1}, \ldots, x_{n+k}: a_{n+k})$ is evaluated. Let $C$ be the class in which the superinitializer appears and let $S$ be the superclass of $C$. If $S$ is generic (\ref{generics}), let $U_1, , \ldots, U_m$ be the actual type arguments passed to $S$ in the superclass clause of $C$. Then, the initializer list of the constructor $S$ (respectively $S.id$) is executed with respect to the bindings that resulted from the evaluation of the argument list, with \THIS{} bound to the current binding of \THIS{}, and the type parameters (if any) of class $S$ bound to the current bindings of $U_1, , \ldots, U_m$. It is a compile-time error if class $S$ does not declare a generative constructor named $S$ (respectively $S.id$) \subsubsection{Factories} \label{factories} A {\em factory} is a constructor prefaced by the built-in identifier (\ref{identifierReference}) \FACTORY{}. \begin{grammar} {\bf factoryConstructorSignature:} \FACTORY{} identifier ({\escapegrammar .}' identifier)? formalParameterList . \end{grammar} %The enclosing scope of a factory constructor is the static scope \ref{} of the class in which it is declared. The {\em return type} of a factory whose signature is of the form \FACTORY{} $M$ or the form \FACTORY{} $M.id$ is $M$ if $M$ is not a generic type; otherwise the return type is $M$ where $T_1, \ldots, T_n$ are the type parameters of the enclosing class It is a compile-time error if $M$ is not the name of the immediately enclosing class. In checked mode, it is a dynamic type error if a factory returns a non-null object whose type is not a subtype of its actual (\ref{actualTypeOfADeclaration}) return type. \rationale{It seems useless to allow a factory to return null. But it is more uniform to allow it, as the rules currently do.} \rationale{Factories address classic weaknesses associated with constructors in other languages. Factories can produce instances that are not freshly allocated: they can come from a cache. Likewise, factories can return instances of different classes. } \paragraph{Redirecting Factory Constructors} \label{redirectingFactoryConstructors} A {\em redirecting factory constructor} specifies a call to a constructor of another class that is to be used whenever the redirecting constructor is called. \begin{grammar} {\bf redirectingFactoryConstructorSignature:} \CONST{}? \FACTORY{} identifier ({\escapegrammar .}' identifier)? formalParameterList =' type ({\escapegrammar .}' identifier)? . \end{grammar} Calling a redirecting factory constructor $k$ causes the constructor $k^\prime$ denoted by $type$ (respectively, $type.identifier$) to be called with the actual arguments passed to $k$, and returns the result of $k^\prime$ as the result of $k$. The resulting constructor call is governed by the same rules as an instance creation expression using \NEW{} (\ref{instanceCreation}). \commentary{ It follows that if $type$ or $type.id$ are not defined, or do not refer to a class or constructor, a dynamic error occurs, as with any other undefined constructor call. The same holds if $k$ is called with fewer required parameters or more positional parameters than $k^\prime$ expects, or if $k$ is called with a named parameter that is not declared by $k^\prime$. } It is a compile-time error if $k$ explicitly specifies a default value for an optional parameter.\commentary{ Default values specified in $k$ would be ignored, since it is the {\em actual} parameters that are passed to $k^\prime$. Hence, default values are disallowed. } It is a compile-time error if a redirecting factory constructor redirects to itself, either directly or indirectly via a sequence of redirections. %does not redirect to a non-redirecting factory constructor or to a generative constructor in a finite number of steps. \rationale{ If a redirecting factory $F_1$ redirects to another redirecting factory $F_2$ and $F_2$ then redirects to $F_1$, then both $F_1$ and $F_2$ are ill-defined. Such cycles are therefore illegal. } It is a static warning if $type$ does not denote a class accessible in the current scope; if $type$ does denote such a class $C$ it is a static warning if the referenced constructor (be it $type$ or $type.id$) is not a constructor of $C$. \commentary{ Note that it is not possible to modify the arguments being passed to $k'$. } % but we have the same issue with other redirecting constructors, no?) \rationale{ At first glance, one might think that ordinary factory constructors could simply create instances of other classes and return them, and that redirecting factories are unnecessary. However, redirecting factories have several advantages: \begin{itemize} \item An abstract class may provide a constant constructor that utilizes the constant constructor of another class. \item A redirecting factory constructors avoids the need for forwarders to repeat the default values for formal parameters in their signatures. %\item A generic factory class that aggregates factory constructors for types it does not implement can still have its type arguments passed correctly. \end{itemize} %An example of the latter point: %} %\begin{dartCode} %\CLASS{} W$<$T$>$ \IMPLEMENTS{} A$<$T$>$ { W(w) {...} ...} %\CLASS{} X$<$T$>$ \IMPLEMENTS{} A$<$T$>$ { X(x) {...} ...} %\CLASS{} Y$<$T$>$ \IMPLEMENTS{} A$<$T$>$ { Y(y) {...} ...} %\CLASS{} Z$<$T$>$ \IMPLEMENTS{} A$<$T$>$ { Z(z) {...} ...} %\CLASS{} F$<$T$>$ { // note that F does not implement A % \STATIC{} F$<$T$>$ idw(w) $=>$ \NEW{} W$<$T$>$(w); // illegal - T not in scope in idw % \FACTORY{} F.idx(x) $=>$ \NEW{} X$<$T$>$(x); % \FACTORY{} F.idy(y) $=>$ \NEW{} Y$<$T$>$(y); % \STATIC{} F idz(z) $=>$ \NEW{} Z(z); // does not capture the type argument %} %\CLASS{} A$<$T$>${ % \FACTORY{} A.idw(w) $=>$ F$<$T$>$.idw(w); %// illegal - cannot pass type parameter to static method % \FACTORY{} A.idx(x) $=> \NEW{}$F$<$T$>$.idx(x); // works, but allocates a gratuitous instance of F % \FACTORY{} A.idy(y) = Y$<$T$>$; // works % \FACTORY{} A.idz(z) $=>$ F.idz(z); // wrong - returns Z$<$Dynamic$>$; no way to pass type argument } %\end{dartCode} It is a compile-time error if $k$ is prefixed with the \CONST{} modifier but $k^\prime$ is not a constant constructor (\ref{constantConstructors}). It is a static warning if the function type of $k^\prime$ is not a subtype of the type of $k$. \commentary{ This implies that the resulting object conforms to the interface of the immediately enclosing class of $k$. } It is a static type warning if any of the type arguments to $k^\prime$ are not subtypes of the bounds of the corresponding formal type parameters of $type$. \subsubsection{Constant Constructors} \label{constantConstructors} A {\em constant constructor} may be used to create compile-time constant (\ref{constants}) objects. A constant constructor is prefixed by the reserved word \CONST{}. \begin{grammar} {\bf constantConstructorSignature:} \CONST{} qualified formalParameterList . \end{grammar} %\commentary{Spell out subtleties: a constant constructor call within the initializer of a constant constructor is treated as a ordinary constructor call (a new), because the arguments cannot be assumed constant anymore. In practice, this means two versions are compiled and analyzed. One for new and one for const.} % \Q{How to specify?} \commentary{All the work of a constant constructor must be handled via its initializers.} It is a compile-time error if a constant constructor is declared by a class that has a non-final instance variable. \commentary{ The above refers to both locally declared and inherited instance variables. } The superinitializer that appears, explicitly or implicitly, in the initializer list of a constant constructor must specify a constant constructor of the superclass of the immediately enclosing class or a compile-time error occurs. Any expression that appears within the initializer list of a constant constructor must be a potentially constant expression, or a compile-time error occurs. A {\em potentially constant expression} is an expression $e$ that would be a valid constant expression if all formal parameters of $e$'s immediately enclosing constant constructor were treated as compile-time constants that were guaranteed to evaluate to an integer, boolean or string value as required by their immediately enclosing superexpression. \commentary{ The difference between a potentially constant expression and a compile-time constant expression (\ref{const}) deserves some explanation. The key issue is whether one treats the formal parameters of a constructor as compile-time constants. If a constant constructor is invoked from a constant object expression, the actual arguments will be required to be compile-time constants. Therefore, if we were assured that constant constructors were always invoked from constant object expressions, we could assume that the formal parameters of a constructor were compile-time constants. However, constant constructors can also be invoked from ordinary instance creation expressions (\ref{new}), and so the above assumption is not generally valid. Nevertheless, the use of the formal parameters of a constant constructor within the constructor is of considerable utility. The concept of potentially constant expressions is introduced to facilitate limited use of such formal parameters. Specifically, we allow the usage of the formal parameters of a constant constructor for expressions that involve built-in operators, but not for constant objects, lists and maps. This allows for constructors such as: } \begin{dartCode} \CLASS{} C \{ \FINAL{} x; \FINAL{} y; \FINAL{} z; \CONST{} C(p, q): x = q, y = p + 100, z = p + q; % what about % \CONST{} C(p, q): x = q, y = p + 100, z = p + 'foo'; % perhaps moot. Current spec says that would be ok; type checker can worry, as can execution, which is at compile time anyway \} \end{dartCode} \commentary{ The assignment to \code{x} is allowed under the assumption that \code{q} is a compile-time constant (even though \code{q} is not, in general a compile-time constant). The assignment to \code{y} is similar, but raises additional questions. In this case, the superexpression of \code{p} is \code{p + 100}, and it requires that \code{p} be a numeric compile-time constant for the entire expression to be considered constant. The wording of the specification allows us to assume that \code{p} evaluates to an integer. A similar argument holds for \code{p} and \code{q} in the assignment to \code{z}. However, the following constructors are disallowed: } \begin{dartCode} \CLASS{} D \{ \FINAL{} w; \CONST{} D.makeList(p): w = \CONST{} [p]; // compile-time error \CONST{} D.makeMap(p): w = \CONST{} \{help'': q\}; // compile-time error \CONST{} D.makeC(p): w = \CONST{} C(p, 12); // compile-time error \} \end{dartCode} \commentary{ The problem is not that the assignments to \code{w} are not potentially constant; they are. However, all these run afoul of the rules for constant lists (\ref{lists}), maps (\ref{maps}) and objects (\ref{const}), all of which independently require their subexpressions to be constant expressions. } \rationale{ All of the illegal constructors of \code{D} above could not be sensibly invoked via \NEW{}, because an expression that must be constant cannot depend on a formal parameter, which may or may not be constant. In contrast, the legal examples make sense regardless of whether the constructor is invoked via \CONST{} or via \NEW{}. Careful readers will of course worry about cases where the actual arguments to \code{C()} are constants, but are not numeric. This is precluded by the following rule, combined with the rules for evaluating constant objects (\ref{const}). } When invoked from a constant object expression, a constant constructor must throw an exception if any of its actual parameters is a value that would prevent one of the potentially constant expressions within it from being a valid compile-time constant. %Discuss External Constructors in ne subsubsection here \subsection{Static Methods} \label{staticMethods} {\em Static methods} are functions, other than getters or setters, whose declarations are immediately contained within a class declaration and that are declared \STATIC{}. The static methods of a class $C$ are those static methods declared by $C$. \rationale{ Inheritance of static methods has little utility in Dart. Static methods cannot be overridden. Any required static function can be obtained from its declaring library, and there is no need to bring it into scope via inheritance. Experience shows that developers are confused by the idea of inherited methods that are not instance methods. Of course, the entire notion of static methods is debatable, but it is retained here because so many programmers are familiar with it. Dart static methods may be seen as functions of the enclosing library. } It is a static warning if a class $C$ declares a static method named $n$ and has a setter named $n=$. %It is a static warning if a class has a static method with the same name as a static member of one of its superclasses. %\rationale{ %This last restriction makes classes more brittle with respect to changes in the class hierarchy. It stems from a general observation that shadowing of names in the same scope is questionable and should elicit a warning. %} %\commentary{ %There is no hiding of static methods, or of static variables. %} \subsection{Static Variables} \label{staticVariables} {\em Static variables} are variables whose declarations are immediately contained within a class declaration and that are declared \STATIC{}. The static variables of a class $C$ are those static variables declared by $C$. %A static variable declaration of one of the forms \code{\STATIC{} $T$ $v$;}, \code{\STATIC{} $T$ $v$ = $e$;} , \code{\STATIC{} \CONST{} $T$ $v$ = $e$;} or \code{\STATIC{} \FINAL{} $T$ $v$ = $e$;} always induces an implicit static getter function (\ref{getters}) with signature %\STATIC{} $T$ \GET{} $v$ %whose invocation evaluates as described below (\ref{evaluationOfStaticVariableGetters}).%to the value stored in $v$. %A static variable declaration of one of the forms \code{\STATIC{} \VAR{} $v$;}, \code{\STATIC{} \VAR{} $v$ = $e$;} , \code{\STATIC{} \CONST{} $v$ = $e$;} or \code{\STATIC{} \FINAL{} $v$ = $e$;} always induces an implicit static getter function with signature %\STATIC{} \GET{} $v$ %whose invocation evaluates as described below (\ref{evaluationOfStaticVariableGetters}).%to the value stored in $v$. %A non-final static variable declaration of the form \code{\STATIC{} $T$ $v$;} or the form \code{\STATIC{} $T$ $v$ = $e$;} always induces an implicit static setter function (\ref{setters}) with signature %\STATIC{} \VOID{} \SET{} $v=(T$ $x)$ %whose execution sets the value of $v$ to the incoming argument $x$. %A static variable declaration of the form \code{\STATIC{} \VAR{} $v$;} or the form \code{\STATIC{} \VAR{} $v$ = $e$;} always induces an implicit static setter function with signature %\STATIC{} \SET{} $v=(x)$ %whose execution sets the value of $v$ to the incoming argument $x$. %Extrernal static functions, getters, setters %\subsubsection{Evaluation of Implicit Static Variable Getters} %\label{evaluationOfStaticVariableGetters} %Let $d$ be the declaration of a static variable $v$. The implicit getter method of $v$ executes as follows: %\begin{itemize} %\item If $d$ is of one of the forms \code{\STATIC{} \VAR{} $v$ = $e$;} , \code{\STATIC{} $T$ $v$ = $e$; }, \code{\STATIC{} \FINAL{} $v$ = $e$; } or \code{\STATIC{} \FINAL{} $T$ $v$ = $e$;} and no value has yet been stored into $v$ then the initializer expression $e$ is evaluated. If, during the evaluation of $e$, the getter for $v$ is referenced, a \code{CyclicInitializationError} is thrown. If the evaluation succeeded yielding an object $o$, let $r = o$, otherwise let $r = \NULL{}$. In any case, $r$ is stored into $v$. The result of executing the getter is $r$. %\item If $d$ is of one of the forms \code{\STATIC{} \CONST{} $v$ = $e$; } or \code{\STATIC{} \CONST{} $T$ $v$ = $e$;} the result of the getter is the value of the compile time constant $e$. %Otherwise %\item The result of executing the getter method is the value stored in $v$. %\end{itemize} \subsection{Superclasses} \label{superclasses} The superclass of a class $C$ that has a with clause \code{\WITH{} $M_1, \ldots, M_k$} and an extends clause \code{\EXTENDS{} S} is the application of mixin (\ref{mixins}) $M_k* \cdots * M_1$ to S. If no with clause is specified then the \EXTENDS{} clause of a class $C$ specifies its superclass. If no \EXTENDS{} clause is specified, then either: \begin{itemize} \item $C$ is \code{Object}, which has no superclass. OR \item Class $C$ is deemed to have an \EXTENDS{} clause of the form \code{\EXTENDS{} Object}, and the rules above apply. \end{itemize} It is a compile-time error to specify an \EXTENDS{} clause for class \code{Object}. \begin{grammar} {\bf superclass:} \EXTENDS{} type . \end{grammar} %The superclass clause of a class C is processed within the enclosing scope of the static scope of C. %\commentary{ %This means that in a generic class, the type parameters of the generic are available in the superclass clause. %} %It is a compile-time error if the \EXTENDS{} clause of a class $C$ includes a type expression that does not denote a class available in the lexical scope of $C$. It is a compile-time error if the \EXTENDS{} clause of a class $C$ specifies a malformed type as a superclass. % too strict? Do we e want extends List to work as List? \commentary{ The type parameters of a generic class are available in the lexical scope of the superclass clause, potentially shadowing classes in the surrounding scope. The following code is therefore illegal and should cause a compile-time error: } \begin{dartCode} class T \{\} /* Compilation error: Attempt to subclass a type parameter */ class G$<$T$>$ extends T \{\} \end{dartCode} A class $S$ is {\em a superclass} of a class $C$ iff either: \begin{itemize} \item $S$ is the superclass of $C$, or \item $S$ is a superclass of a class $S^{\prime}$ and $S^{\prime}$ is a superclass of $C$. \end{itemize} It is a compile-time error if a class $C$ is a superclass of itself. \subsubsection{Inheritance and Overriding} \label{inheritanceAndOverriding} %A class $C$ {\em inherits} any accessible instance members of its superclass that are not overridden by members declared in $C$. Let $C$ be a class, let $A$ be a superclass of $C$, and let $S_1 \ldots S_k$ be superclasses of $C$ that are also subclasses of $A$. $C$ {\em inherits} all accessible instance members of $A$ that have not been overridden by a declaration in $C$ or in at least one of $S_1 \ldots S_k$. \rationale { It would be more attractive to give a purely local definition of inheritance, that depended only on the members of the direct superclass $S$. However, a class $C$ can inherit a member $m$ that is not a member of its superclass $S$. This can occur when the member $m$ is private to the library $L_1$ of $C$, whereas $S$ comes from a different library $L_2$, but the superclass chain of $S$ includes a class declared in $L_1$. } A class may override instance members that would otherwise have been inherited from its superclass. Let $C = S_0$ be a class declared in library $L$, and let $\{S_1 \ldots S_k\}$ be the set of all superclasses of $C$, where $S_i$ is the superclass of $S_{i-1}$ for $i \in 1 .. k$. Let $C$ declare a member $m$, and let $m^\prime$ be a member of $S_j, j \in 1 .. k$, that has the same name as $m$, such that $m^\prime$ is accessible to $L$. Then $m$ overrides $m^\prime$ if $m^\prime$ is not already overridden by a member of at least one of $S_1 \ldots S_{j-1}$ and neither $m$ nor $m^\prime$ are fields. %Let $C$ be a class declared in library $L$, with superclass $S$ and let $C$ declare an instance member $m$, and assume $S$ declares an instance member $m^\prime$ with the same name as $m$. Then $m$ {\em overrides} $m^\prime$ iff $m^\prime$ is accessible (\ref{privacy}) to $L$, $m$ has the same name as $m^\prime$ and neither $m$ nor $m^\prime$ are fields. \commentary{Fields never override each other. The getters and setters induced by fields do.} \rationale{Again, a local definition of overriding would be preferable, but fails to account for library privacy. } Whether an override is legal or not is described elsewhere in this specification (see \ref{instanceMethods}, \ref{getters} and \ref{setters}). \commentary{For example getters may not legally override methods and vice versa. Setters never override methods or getters, and vice versa, because their names always differ. } \rationale{ It is nevertheless convenient to define the override relation between members in this way, so that we can concisely describe the illegal cases. } \commentary{ Note that instance variables do not participate in the override relation, but the getters and setters they induce do. Also, getters dont override setters and vice versa. Finally, static members never override anything. } It is a static warning if a non-abstract class inherits an abstract method. \commentary { For convenience, here is a summary of the relevant rules. Remember that this is not normative. The controlling language is in the relevant sections of the specification. \begin{enumerate} \item There is only one namespace for getters, setters, methods and constructors (\ref{scoping}). A field $f$ introduces a getter $f$ and a setter $f=$ (\ref{instanceVariables}, \ref{staticVariables}). When we speak of members here, we mean accessible fields, getters, setters and methods (\ref{classes}). \item You cannot have two members with the same name in the same class - be they declared or inherited (\ref{scoping}, \ref{classes}). \item Static members are never inherited. \item It is a warning if you have an static member named $m$ in your class or any superclass (even though it is not inherited) and an instance member of the same name (\ref{instanceMethods}, \ref{getters}, \ref{setters}). \item It is a warning if you have a static setter $v=$, and an instance member $v$ (\ref{setters}). \item It is a warning if you have a static getter $v$ and an instance setter $v=$ (\ref{getters}). \item If you define an instance member named $m$, and your superclass has an instance member of the same name, they override each other. This may or may not be legal. \item \label{typeSigAssignable} If two members override each other, it is a static warning if their type signatures are not assignable to each other (\ref{instanceMethods}, \ref{getters}, \ref{setters}) (and since these are function types, this means the same as "subtypes of each other"). \item \label{requiredParams} If two members override each other, it is a static warning if the overriding member has more required parameters than the overridden one (\ref{instanceMethods}). \item \label{optionalPositionals} If two members override each other, it is a static warning if the overriding member has fewer positional parameters than the the overridden one (\ref{instanceMethods}). \item \label{namedParams} If two members override each other, it is a static warning if the overriding member does not have all the named parameters that the the overridden one has (\ref{instanceMethods}). \item Setters, getters and operators never have optional parameters of any kind; it's a compile-time error (\ref{operators}, \ref{getters}, \ref{setters}). \item It is a compile-time error if a member has the same name as its enclosing class (\ref{classes}). \item A class has an implicit interface (\ref{classes}). \item Superinterface members are not inherited by a class, but are inherited by its implicit interface. Interfaces have their own inheritance rules (\ref{interfaceInheritanceAndOverriding}). \item A member is abstract if it has no body and is not labeled \EXTERNAL{} (\ref{abstractInstanceMembers}, \ref{externalFunctions}). \item A class is abstract iff it is explicitly labeled \ABSTRACT{}.% or if it declares (not just inherits) an abstract member (\ref{classes}). \item It is a static warning a concrete class has an abstract member (declared or inherited). \item It is a static warning and a dynamic error to call a non-factory constructor of an abstract class (\ref{new}). \item If a class defines an instance member named $m$, and any of its superinterfaces have a member named $m$, the interface of the class overrides $m$. \item An interface inherits all members of its superinterfaces that are not overridden and not members of multiple superinterfaces. \item If multiple superinterfaces of an interface define a member with the same name $m$, then at most one member is inherited. That member (if it exists) is the one whose type is a subtype of all the others. If there is no such member, then: \begin{itemize} \item A static warning is given. \item If possible the interface gets a member named $m$ that has the minimum number of required parameters among all the members in the superinterfaces, the maximal number of positionals, and the superset of named parameters. The types of these are all \DYNAMIC{}. If this is impossible then no member $m$ appears in the interface. \end{itemize} (\ref{interfaceInheritanceAndOverriding}) \item Rule \ref{typeSigAssignable} applies to interfaces as well as classes (\ref{interfaceInheritanceAndOverriding}). \item It is a static warning if a concrete class does not have an implementation for a method in any of its superinterfaces unless it declares its own \cd{noSuchMethod} method (\ref{superinterfaces}). \item The identifier of a named constructor cannot be the same as the name of a member declared (as opposed to inherited) in the same class (\ref{constructors}). \end{enumerate} } %Can we have abstract getters and setters? \subsection{Superinterfaces} \label{superinterfaces} % what about rules about classes that fail to implement their interfaces? A class has a set of direct superinterfaces. This set includes the interface of its superclass and the interfaces specified in the the \IMPLEMENTS{} clause of the class. % and any superinterfaces specified by interface injection (\ref{interfaceInjection}). \Q{The latter needs to be worded carefully - when do interface injection clauses execute and in what scope?} \begin{grammar} {\bf interfaces:} \IMPLEMENTS{} typeList . \end{grammar} It is a compile-time error if the \IMPLEMENTS{} clause of a class $C$ specifies a type variable as a superinterface. It is a compile-time error if the \IMPLEMENTS{} clause of a class $C$ specifies a malformed type as a superinterface It is a compile-time error if the \IMPLEMENTS{} clause of a class $C$ specifies type \DYNAMIC{} as a superinterface. It is a compile-time error if the \IMPLEMENTS{} clause of a class $C$ specifies a type $T$ as a superinterface more than once. It is a compile-time error if the superclass of a class $C$ is specified as a superinterface of $C$. \rationale{ One might argue that it is harmless to repeat a type in the superinterface list, so why make it an error? The issue is not so much that the situation described in program source is erroneous, but that it is pointless. As such, it is an indication that the programmer may very well have meant to say something else - and that is a mistake that should be called to her or his attention. Nevertheless, we could simply issue a warning; and perhaps we should and will. That said, problems like these are local and easily corrected on the spot, so we feel justified in taking a harder line. } It is a compile-time error if the interface of a class $C$ is a superinterface of itself. Let $C$ be a concrete class that does not declare its own \code{noSuchMethod()} method. It is a static warning if the implicit interface of $C$ includes an instance member $m$ of type $F$ and $C$ does not declare or inherit a corresponding instance member $m$ of type $F'$ such that $F' <: F$. \commentary{A class does not inherit members from its superinterfaces. However, its implicit interface does. } \rationale { We choose to issue these warnings only for concrete classes; an abstract class might legitimately be designed with the expectation that concrete subclasses will implement part of the interface. We also disable these warnings if a \code{noSuchMethod()} declaration is present. In such cases, the supported interface is going to be implemented via \code{noSuchMethod()} and no actual declarations of the implemented interface's members are needed. This allows proxy classes for specific types to be implemented without provoking type warnings. } It is a static warning if the implicit interface of a class $C$ includes an instance member $m$ of type $F$ and $C$ declares or inherits a corresponding instance member $m$ of type $F'$ if $F'$ is not a subtype of $F$. \rationale{ However, if a class does explicitly declare a member that conflicts with its superinterface, this always yields a static warning. } %It is a static warning if an imported superinterface of a class $C$ declares private members. % Should we ignore unimplemented private members? %\rationale{This last rule is problematic. As code evolves in one library ($L_1$) it may add private members to a class $I_1$ implemented or inherited in another library $L_2$ breaking $L_1$. This is a direct result of coupling an interface based type system with library based privacy. We are considering alternative semantics that might help resolve this issue. %} %\commentary{However, it is perfectly acceptable if a type mentioned in the implements clause is mentioned as a superinterface in an interface injection clause. %} %\rationale{We disallow repetition of a type in a given implements clause, as that is a localized mistake. However, separate clauses (that is the original class and various injections) may evolve separately over time, and we don't want to cause breakage. For example %class C implements I1 {...}; // class declaration %somewhere someone realizes that C could implement I2 class C implements I2; // injection %later, the author of C decides to support I2 %class C implements I1, I2 {...}; // class declaration %this should not cause breakage. %} % \rationale{This avoids the issues with so-called miranda methods etc. } \section{Interfaces} \label{interfaces} An {\em interface} defines how one may interact with an object. An interface has methods, getters and setters and a set of superinterfaces. \subsection{Superinterfaces} \label{interfaceSuperinterfaces} An interface has a set of direct superinterfaces. An interface $J$ is a superinterface of an interface $I$ iff either $J$ is a direct superinterface of $I$ or $J$ is a superinterface of a direct superinterface of $I$. \subsubsection{Inheritance and Overriding} \label{interfaceInheritanceAndOverriding} Let $J$ be an interface and $K$ be a library. We define $inherited(J, K)$ to be the set of members $m$ such that all of the following hold: \begin{itemize} \item $m$ is accessible to $K$ and \item $A$ is a direct superinterface of $J$ and either \begin{itemize} \item $m$ is a member of $A$ or \item $m$ is a member of $inherited(A, K)$. \end{itemize} \item $m$ is not overridden by $J$. \end{itemize} Furthermore, we define $overrides(J, K)$ to be the set of members $m^\prime$ such that all of the following hold: \begin{itemize} \item $J$ is the implicit interface of a class $C$. \item $C$ declares a member $m$. \item $m^\prime$ has the same name as $m$. \item $m^\prime$ is accessible to $K$. \item $A$ is a direct superinterface of $J$ and either \begin{itemize} \item $m^\prime$ is a member of $A$ or \item $m^\prime$ is a member of $inherited(A, K)$. \end{itemize} \end{itemize} Let $I$ be the implicit interface of a class $C$ declared in library $L$. $I$ {\em inherits} all members of $inherited(I, L)$ and $I$ {\em overrides} $m^\prime$ if $m^\prime \in overrides(I, L)$. All the static warnings pertaining to the overriding of instance members given in section \ref{classes} above hold for overriding between interfaces as well. It is a static warning if $m$ is a method and $m^\prime$ is a getter, or if $m$ is a getter and $m^\prime$ is a method. %Let $I = S_0$ be the implicit interface of a class $C$ declared in library $L$, and let $\{S_1 \ldots S_k\}$ be the set of all superinterfaces of $I$. %Let $I$ be the implicit interface of a class $C$. $I$ inherits any instance members of its superinterfaces that are not overridden by members declared in $C$. % tighten definition? do we need chain as for classes? Definition for interface override? However, if the above rules would cause multiple members $m_1, \ldots, m_k$ with the same name $n$ to be inherited (because identically named members existed in several superinterfaces) then at most one member is inherited. If some but not all of the $m_i, 1 \le i \le k$ are getters none of the $m_i$ are inherited, and a static warning is issued. Otherwise, if the static types $T_1, \ldots, T_k$ of the members $m_1, \ldots, m_k$ are not identical, then there must be a member $m_x$ such that $T_x <: T_i, 1 \le x \le k$ for all $i \in 1..k$, or a static type warning occurs. The member that is inherited is $m_x$, if it exists; otherwise: \begin{itemize} \item Let $numberOfPositionals(f)$ denote the number of positional parameters of a function $f$, and let $numberOfRequiredParams(f)$ denote the number of required parameters of a function $f$. Furthermore, let $s$ denote the set of all named parameters of the $m_1, \ldots, m_k$. Then let $h = max(numberOfPositionals(m_i)),$ $r = min(numberOfRequiredParams(m_i)), i \in 1..k$. If $r \le h$ then $I$ has a method named $n$, with $r$ required parameters of type \DYNAMIC{}, $h$ positional parameters of type \DYNAMIC{}, named parameters $s$ of type \DYNAMIC{} and return type \DYNAMIC{}. \item Otherwise none of the members $m_1, \ldots, m_k$ is inherited. \end{itemize} \commentary{The only situation where the runtime would be concerned with this would be during reflection, if a mirror attempted to obtain the signature of an interface member. } \rationale{ The current solution is a tad complex, but is robust in the face of type annotation changes. Alternatives: (a) No member is inherited in case of conflict. (b) The first m is selected (based on order of superinterface list) (c) Inherited member chosen at random. (a) means that the presence of an inherited member of an interface varies depending on type signatures. (b) is sensitive to irrelevant details of the declaration and (c) is liable to give unpredictable results between implementations or even between different compilation sessions. } % Need warnings if overrider conflicts with overriddee either because signatures are incompatible or because done is a method and one is a getter or setter. \section{Mixins} \label{mixins} A mixin describes the difference between a class and its superclass. A mixin is always derived from an existing class declaration. It is a compile-time error if a declared or derived mixin refers to \SUPER{}. It is a compile-time error if a declared or derived mixin explicitly declares a constructor. It is a compile-time error if a mixin is derived from a class whose superclass is not \code{Object}. \rationale{ These restrictions are temporary. We expect to remove them in later versions of Dart. The restriction on the use of \SUPER{} avoids the problem of rebinding \SUPER{} when the mixin is bound to difference superclasses. The restriction on constructors simplifies the construction of mixin applications because the process of creating instances is simpler. The restriction on the superclass means that the type of a class from which a mixin is derived is always implemented by any class that mixes it in. This allows us to defer the question of whether and how to express the type of the mixin independently of its superclass and super interface types. Reasonable answers exist for all these issues, but their implementation is non-trivial. } \subsection{Mixin Application} \label{mixinApplication} A mixin may be applied to a superclass, yielding a new class. Mixin application occurs when a mixin is mixed into a class declaration via its \WITH{} clause. The mixin application may be used to extend a class per section (\ref{classes}); alternately, a class may be defined as a mixin application as described in this section. \begin{grammar} {\bf mixinApplicationClass:} identifier typeParameters? =' mixinApplication {\escapegrammar ;}' . {\bf mixinApplication:} type mixins interfaces? . \end{grammar} A mixin application of the form \code{$S$ \WITH{} $M$;} defines a class $C$ with superclass $S$. A mixin application of the form \code{$S$ \WITH{} $M_1, \ldots, M_k$;} defines a class $C$ whose superclass is the application of the mixin composition (\ref{mixinComposition}) $M_{k-1} * \ldots * M_1$ to $S$. In both cases above, $C$ declares the same instance members as $M$ (respectively, $M_k$). If any of the instance fields of $M$ (respectively, $M_k$) have initializers, they are executed in the scope of $M$ (respectively, $M_k$) to initialize the corresponding fields of $C$. For each generative constructor named $q_i(T_{i1}$ $a_{i1}, \ldots , T_{ik_i}$ $a_{ik_i}), i \in 1..n$ of $S$, $C$ has an implicitly declared constructor named $q'_i = [C/S]q_i$ of the form $q'_i(a_{i1}, \ldots , a_{ik_i}):\SUPER(a_{i1}, \ldots , a_{ik_i});$. % The types must be given in the copied constructor. It was tempting to elide them; after all, checked mode will catch things in the % super call - but this may be a problem for tools. % We interpret this instead as S includes the generic parameters, so the signature has already substituted them. % Default values may not be replicable for optional params due to scoping/privacy. % How to describe and implement %The class $C$ has an implicitly declared nullary generative constructor with no initializer list and no body. If the mixin application declares support for interfaces, the resulting class implements those interfaces. It is a compile-time error if $S$ is a malformed type. It is a compile-time error if $M$ (respectively, any of $M_1, \ldots, M_k$) is a malformed type. It is a compile time error if a well formed mixin cannot be derived from $M$ (respectively, from each of $M_1, \ldots, M_k$). Let $K$ be a class declaration with the same constructors, superclass and interfaces as $C$, and the instance members declared by $M$ (respectively $M_1, \ldots, M_k$). It is a static warning if the declaration of $K$ would cause a static warning. It is a compile-time error if the declaration of $K$ would cause a compile-time error. \commentary{ If, for example, $M$ declares an instance member $im$ whose type is at odds with the type of a member of the same name in $S$, this will result in a static warning just as if we had defined $K$ by means of an ordinary class declaration extending $S$, with a body that included $im$. %Another implication of this definition is that one cannot apply a mixin to a superclass that does not provide a nullary constructor. } The effect of a class definition of the form \code{\CLASS{} $C$ = $M$; } or the form \code{\CLASS{} $C$ = $M$; } in library $L$ is to introduce the name $C$ into the scope of $L$, bound to the class (\ref{classes}) defined by the mixin application $M$. The name of the class is also set to $C$. Iff the class is prefixed by the built-in identifier \ABSTRACT{}, the class being defined is an abstract class. \subsection{Mixin Composition} \label{mixinComposition} \rationale{ Dart does not directly support mixin composition, but the concept is useful when defining how the superclass of a class with a mixin clause is created. } The {\em composition of two mixins}, $M_1$ and $M_2$, written $M_1 * M_2$ defines an anonymous mixin such that for any class $S$, the application of $M_1 * M_2$ to $S$ is equivalent to \code{\ABSTRACT{} \CLASS{} $Id_1 = Id_2$ \WITH{} $M_1$;} where $Id_2$ denotes \code{\ABSTRACT{} \CLASS{} $Id_2 = S$ \WITH{} $M_2$; } and $Id_1$ and $Id_2$ are unique identifiers that do not exist anywhere in the program. \rationale{ The classes produced by mixin composition are regarded as abstract because they cannot be instantiated independently. They are only introduced as anonymous superclasses of ordinary class declarations and mixin applications. Consequently, no warning is given if a mixin composition includes abstract members, or incompletely implements an interface. } Mixin composition is associative. \commentary{ Note that any subset of $M_1$, $M_2$ and $S$ may or may not be generic. For any non-generic declaration, the corresponding type parameters may be elided, and if no type parameters remain in the derived declarations $Id_1$ and/or $Id_2$ then the those declarations need not be generic either. } \section{Generics} \label{generics} 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. \begin{grammar} {\bf typeParameter:} metadata identifier (\EXTENDS{} type)? . {\bf typeParameters:} <' typeParameter (,' typeParameter)* >' . \end{grammar} 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. The type parameters of a generic $G$ are in scope in the bounds of all of the type 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 exist) and in the body of $G$. However, a type parameter is considered to be a malformed type when referenced by a static member. \rationale{ 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 generic. However, a type variable may be referenced from an instance initializer, even though \THIS{} is not available. } \commentary{ Because type parameters are in scope in their bounds, we support F-bounded quantification (if you don't know what that is, don't ask). This enables typechecking code such as: } \begin{dartCode} \INTERFACE{} Ordered$<$T$>$ \{ operator $>$ (T x); \} \CLASS{} Sorter$<$T \EXTENDS{} Ordered$<$T$>>$ \{ sort(List$<$T$>$ l) {... l[n] $<$ l[n+1] ...} \} \end{dartCode} \commentary{ Even where type parameters are in scope there are numerous restrictions at this time: \begin{itemize} \item A type parameter cannot be used to name a constructor in an instance creation expression (\ref{instanceCreation}). \item A type parameter cannot be used as a superclass or superinterface (\ref{superclasses}, \ref{superinterfaces}, \ref{interfaceSuperinterfaces}). \end{itemize} The normative versions of these are given in the appropriate sections of this specification. Some of these restrictions may be lifted in the future. } %A generic has a type parameter scope. The enclosing scope of a type parameter scope of a generic G is the enclosing scope of G. %class T {...} %class G extends T; %By current rules, this is illegal. Make sure we preserve this. %\subsection{Interface Injection} %\label{interfaceInjection} %An {\em interface injection declaration} causes a pre-existing class $S$ to be considered a subinterface of another interface $I$. It is a static type warning if $S$ is not a structural subtype of $I$. However, the subinterface relations implied by the interface injection declaration are considered to hold by both the typechecker and the runtime, regardless. %\begin{grammar} %classInterfaceInjection: %class qualified typeParameters? interfaces '{\escapegrammar ;}' % . %interfaceInterfaceInjection: %interface qualified typeParameters? superinterfaces '{\escapegrammar ;}' %. %\end{grammar} %\rationale{Since subinterface relations can be tested dynamically via \IS{}, interface injection is not just a directive to the static checker. The dynamic relations implied must hold regardless of whether a static typecheck has succeeded, or has been performed at all. This makes sense from the perspective of preserving programmer intent. The injection describes a nominal type relation that the programmer wishes to hold. Just as a supertype mentioned within a class declaration is considered a supertype even though type errors might arise among (say) overridden and overriding methods, so it must be that the relation implied by an injection holds regardless of type errors. %In addition, this decision helps to produce meaningful and localized error messages. Any errors are reported at the point of injection rather than at program points that rely on the relation (a well known problem with structural subtyping in OO systems). %} %\Q{When does an interface injection take effect? When the containing library is loaded? %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. %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 this a weird security issue? %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 assumption (no mutually suspicious code in the same isolate) is suspect but it seems there is nothing to be done at this point. %If libs are first class, they get created dynamically in order, and new libs might modify the type relations among other libs types - but then it is clear when that happened and order is ok. %} %It is a compile-time error if a type $T$ appears more than once in the implements or eextends clause of an interface injection. \section{Metadata} \label{metadata} Dart supports metadata which is used to attach user defined annotations to program structures. \begin{grammar} {\bf metadata:} (@' qualified ({\escapegrammar .'} identifier)? (arguments)?)* . \end{grammar} Metadata consists of a series of annotations, each of which begin with the character @, followed by a constant expression that starts with an identifier. It is a compile time error if the expression is not one of the following: \begin{itemize} \item A reference to a compile-time constant variable. \item The name of a class. \item A call to a constant constructor. \end{itemize} Metadata is associated with the abstract syntax tree of the program construct $p$ that immediately follows the metadata, assuming $p$ is not itself metadata or a comment. Metadata can be retrieved at runtime via a reflective call, provided the annotated program construct $p$ is accessible via reflection. \commentary{ Obviously, metadata can also be retrieved statically by parsing the program and evaluating the constants via a suitable interpreter. In fact many if not most uses of metadata are entirely static. } \rationale{ It is important that no runtime overhead be incurred by the introduction of metadata that is not actually used. Because metadata only involves constants, the time at which it is computed is irrelevant so that implementations may skip the metadata during ordinary parsing and execution and evaluate it lazily. } \commentary{ It is possible to associate metadata with constructs that may not be accessible via reflection, such as local variables (though it is conceivable that in the future, richer reflective libraries might provide access to these as well). This is not as useless as it might seem. As noted above, the data can be retrieved statically if source code is available. } Metadata can appear before a library, class, typedef, type parameter, constructor, factory, function, field, parameter, or variable declaration and before an import or export directive. The constant expression given in an annotation is type checked and evaluated in the scope surrounding the declaration being annotated. \section{Expressions} \label{expressions} An {\em expression} is a fragment of Dart code that can be evaluated at run time to yield a {\em value}, which is always an object. Every expression has an associated static type (\ref{staticTypes}). Every value has an associated dynamic type (\ref{dynamicTypeSystem}). \begin{grammar} {\bf expression:}assignableExpression assignmentOperator expression; conditionalExpression cascadeSection*; throwExpression . {\bf expressionWithoutCascade:}assignableExpression assignmentOperator expressionWithoutCascade; conditionalExpression; throwExpressionWithoutCascade . {\bf expressionList:} expression (,' expression)* %should these be top level expressions? . \end{grammar} \begin{grammar} {\bf primary:}thisExpression; \SUPER{} assignableSelector; functionExpression; literal; identifier; newExpression; constObjectExpression; (' expression )' . \end{grammar} An expression $e$ may always be enclosed in parentheses, but this never has any semantic effect on $e$. \commentary{ Sadly, it may have an effect on the surrounding expression. Given a class $C$ with static method $m => 42$, $C.m()$ returns 42, but $(C).m()$ produces a \code{NoSuchMethodError}. This anomaly can be corrected by ensuring that every instance of \code{Type} has instance members corresponding to its static members. This issue may be addressed in future versions of Dart . } \subsubsection{Object Identity} \label{objectIdentity} The predefined Dart function \cd{identical()} is defined such that \code{identical($c_1$, $c_2$)} iff: \begin{itemize} \item $c_1$ evaluates to either \NULL{} or an instance of \code{bool} and \code{$c_1$ == $c_2$}, OR \item $c_1$ and $c_2$ are instances of \code{int} and \code{$c_1$ == $c_2$}, OR \item $c_1$ and $c_2$ are constant strings and \code{$c_1$ == $c_2$}, OR \item $c_1$ and $c_2$ are instances of \cd{double} and one of the following holds: \begin{itemize} \item $c_1$ and $c_2$ are non-zero and \code{$c_1$ == $c_2$}. \item Both $c_1$ and $c_2$ are $+0.0$. \item Both $c_1$ and $c_2$ are $-0.0$. \item Both $c_1$ and $c_2$ represent a NaN value. \end{itemize} OR \item $c_1$ and $c_2$ are constant lists that are defined to be identical in the specification of literal list expressions (\ref{lists}), OR \item $c_1$ and $c_2$ are constant maps that are defined to be identical in the specification of literal map expressions (\ref{maps}), OR \item $c_1$ and $c_2$ are constant objects of the same class $C$ and each member field of $c_1$ is identical to the corresponding field of $c_2$. OR \item $c_1$ and $c_2$ are the same object. \end{itemize} \commentary{ The definition of \cd{identity} for doubles differs from that of equality in that a NaN is equal to itself, and that negative and positive zero are distinct. } \rationale{ The definition of equality for doubles is dictated by the IEEE 754 standard, which posits that NaNs do not obey the law of reflexivity. Given that hardware implements these rules, it is necessary to support them for reasons of efficiency. The definition of identity is not constrained in the same way. Instead, it assumes that bit-identical doubles are identical. The rules for identity make it impossible for a Dart programmer to observe whether a boolean or numerical value is boxed or unboxed. } \subsection{Constants} \label{constants} A {\em constant expression} is an expression whose value can never change, and that can be evaluated entirely at compile time. A constant expression is one of the following: \begin{itemize} \item A literal number (\ref{numbers}). \item A literal boolean (\ref{booleans}). \item A literal string (\ref{strings}) where any interpolated expression (\ref{stringInterpolation}) is a compile-time constant that evaluates to a numeric, string or boolean value or to \NULL{}. \rationale{It would be tempting to allow string interpolation where the interpolated value is any compile-time constant. However, this would require running the \code{toString()} method for constant objects, which could contain arbitrary code.} \item A literal symbol (\ref{symbols}). \item \NULL{} (\ref{null}). \item A qualified reference to a static constant variable (\ref{variables}). \commentary {For example, If class C declares a constant static variable v, C.v is a constant. The same is true if C is accessed via a prefix p; p.C.v is a constant. } \item An identifier expression that denotes a constant variable, class or a type alias. \item A constant constructor invocation (\ref{const}). \item A constant list literal (\ref{lists}). \item A constant map literal (\ref{maps}). \item A simple or qualified identifier denoting a top-level function (\ref{functions}) or a static method (\ref{staticMethods}). \item A parenthesized expression \code{($e$)} where $e$ is a constant expression. \item An expression of the form \code{identical($e_1$, $e_2$)} where $e_1$ and $e_2$ are constant expressions and \code{identical()} is statically bound to the predefined dart function \code{identical()} discussed above (\ref{objectIdentity}). \item An expression of one of the forms \code{$e_1$ == $e_2$} or \code{$e_1$ != $e_2$} where $e_1$ and $e_2$ are constant expressions that evaluate to a numeric, string or boolean value or to \NULL{}. \item An expression of one of the forms \code{!$e$}, \code{$e_1$ \&\& $e_2$} or \code{$e_1 || e_2$}, where $e$, $e_1$ and $e_2$ are constant expressions that evaluate to a boolean value. \item An expression of one of the forms \~{}$e$, $e_1$ \^{} $e_2$, \code{$e_1$ \& $e_2$}, $e_1 | e_2$, $e_1 >> e_2$ or $e_1 << e_2$, where $e$, $e_1$ and $e_2$ are constant expressions that evaluate to an integer value or to \NULL{}. \item An expression of one of the forms \code{$-e$}, \code{$e_1 + e_2$}, \code{$e_1$ - $e_2$}, \code{$e_1$ * $e_2$}, \code{$e_1$ / $e_2$,} \code{$e_1$ \~{}/ $e_2$}, \code{$e_1 > e_2$}, \code{$e_1 < e_2$}, \code{$e_1$ $>$= $e_2$}, \code{$e_1$ $<$= $e_2$} or \code{$e_1$ \% $e_2$}, where $e$, $e_1$ and $e_2$ are constant expressions that evaluate to a numeric value or to \NULL{}. \item An expression of the form \code{$e_1$?$e_2$:$e3$} where where $e_1$, $e_2$ and $e_3$ are constant expressions and $e_1$ evaluates to a boolean value. \end{itemize} % null in all the expressions % designed so constants do not depend on check diode being on or not. It is a compile-time error if an expression is required to be a constant expression but its evaluation would raise an exception. % so, checked mode? analyzers? editor/development compilers? \commentary{ Note that there is no requirement that every constant expression evaluate correctly. Only when a constant expression is required (e.g., to initialize a constant variable, or as a default value of a formal parameter, or as metadata) do we insist that a constant expression actually be evaluated successfully at compile time. The above is not dependent on program control-flow. The mere presence of a required compile time constant whose evaluation would fail within a program is an error. This also holds recursively: since compound constants are composed out of constants, if any subpart of a constant would raise an exception when evaluated, that is an error. On the other hand, since implementations are free to compile code late, some compile-time errors may manifest quite late. } \begin{dartCode} \CONST{} x = 1/0; \FINAL{} y = 1/0; \CLASS{} K \{ m1() \{ \VAR{} z = \FALSE{}; \IF{} (z) \{\RETURN{} x; \} \ELSE{} \{ \RETURN{} 2;\} \} m2() \{ \IF{} (\TRUE{}) \{\RETURN{} y; \} \ELSE{} \{ \RETURN{} 3;\} \} \} \end{dartCode} \commentary{An implementation is free to immediately issue a compilation error for \code{x}, but it is not required to do so. It could defer errors if it does not immediately compile the declarations that reference \code{x}. For example, it could delay giving a compilation error about the method \code{m1} until the first invocation of \code{m1}. However, it could not choose to execute \code{m1}, see that the branch that refers to \code{x} is not taken and return 2 successfully. The situation with respect to an invocation \code{m2} is different. Because \code{y} is not a compile-time constant (even though its value is), one need not give a compile-time error upon compiling \code{m2}. An implementation may run the code, which will cause the getter for \code{y} to be invoked. At that point, the initialization of \code{y} must take place, which requires the initializer to be compiled, which will cause a compilation error. } \rationale{ The treatment of \NULL{} merits some discussion. Consider \code{\NULL{} + 2}. This expression always causes an error. We could have chosen not to treat it as a constant expression (and in general, not to allow \NULL{} as a subexpression of numeric or boolean constant expressions). There are two arguments for including it: \begin{enumerate} \item It is constant. We can evaluate it at compile-time. \item It seems more useful to give the error stemming from the evaluation explicitly. \end{enumerate} } It is a compile-time error if the value of a compile-time constant expression depends on itself. \commentary{ As an example, consider: } \begin{dartCode} \CLASS{} CircularConsts\{ // Illegal program - mutually recursive compile-time constants \STATIC{} \CONST{} i = j; // a compile-time constant \STATIC{} \CONST{} j = i; // a compile-time constant \} \end{dartCode} \begin{grammar} {\bf literal:}nullLiteral; booleanLiteral; numericLiteral; stringLiteral; symbolLiteral; mapLiteral; listLiteral . \end{grammar} \subsection{Null} \label{null} The reserved word \NULL{} denotes the {\em null object}. %\Q{Any methods, such as \code{isNull}?} \begin{grammar} {\bf nullLiteral:} \NULL{} . \end{grammar} The null object is the sole instance of the built-in class \code{Null}. Attempting to instantiate \code{Null} causes a run-time error. It is a compile-time error for a class to attempt to extend or implement \code{Null}. Invoking a method on \NULL{} yields a \code{NoSuchMethodError} unless the method is explicitly implemented by class \code{Null}. The static type of \NULL{} is $\bot$. \rationale{The decision to use $\bot$ instead of \code{Null} allows \NULL{} to be be assigned everywhere without complaint by the static checker. } \subsection{Numbers} \label{numbers} A {\em numeric literal} is either a decimal or hexadecimal integer of arbitrary size, or a decimal double. \begin{grammar} {\bf numericLiteral:}NUMBER; HEX\_NUMBER . {\bf NUMBER:} DIGIT+ ({\escapegrammar.}' DIGIT+)? EXPONENT?; {\escapegrammar .}' DIGIT+ EXPONENT? . {\bf EXPONENT:} (e' $|$ E') ('+' $|$ -)? DIGIT+ . {\bf HEX\_NUMBER:}0x' HEX\_DIGIT+; 0X' HEX\_DIGIT+ . {\bf HEX\_DIGIT:}a'{\escapegrammar ..}'f'; A'{\escapegrammar ..}'F'; DIGIT . \end{grammar} If a numeric literal begins with the prefix 0x' or 0X', it denotes the hexadecimal integer represented by the part of the literal following 0x' (respectively 0X'). Otherwise, if the numeric literal does not include a decimal point it denotes a decimal integer. Otherwise, the numeric literal denotes a 64 bit double precision floating point number as specified by the IEEE 754 standard. In principle, the range of integers supported by a Dart implementations is unlimited. In practice, it is limited by available memory. Implementations may also be limited by other considerations. \commentary{ For example, implementations may choose to limit the range to facilitate efficient compilation to Javascript. These limitations should be relaxed as soon as technologically feasible. } It is a compile-time error for a class to attempt to extend or implement \code{int}. It is a compile-time error for a class to attempt to extend or implement \code{double}. It is a compile-time error for any type other than the types \code{int} and \code{double} to attempt to extend or implement \code{num}. An {\em integer literal} is either a hexadecimal integer literal or a decimal integer literal. Invoking the getter \code{runtimeType} on an integer literal returns the \code{Type} object that is the value of the expression \code{int}. The static type of an integer literal is \code{int}. A {\em literal double} is a numeric literal that is not an integer literal. Invoking the getter \code{runtimeType} on a literal double returns the \code{Type} object that is the value of the expression \code{double}. The static type of a literal double is \code{double}. \subsection{Booleans} \label{booleans} The reserved words \TRUE{} and \FALSE{} denote objects that represent the boolean values true and false respectively. They are the {\em boolean literals}. \begin{grammar} {\bf booleanLiteral:}\TRUE{}; \FALSE{} . \end{grammar} Both \TRUE{} and \FALSE{} implement the built-in class \code{bool}. It is a compile-time error for a class to attempt to extend or implement\code{ bool}. \commentary{ It follows that the two boolean literals are the only two instances of \code{bool}. } Invoking the getter \code{runtimeType} on a boolean literal returns the \code{Type} object that is the value of the expression \code{bool}. The static type of a boolean literal is \code{bool}. \subsubsection{Boolean Conversion} \label{booleanConversion} {\em Boolean conversion} maps any object $o$ into a boolean. Boolean conversion is defined by the function \begin{dartCode} (bool v)\{ \ASSERT{}(v != \NULL{}); % \IF{} (\NULL{} == v) \{ \THROW{} \NEW{} AssertionError('null is not a bool')\}; \RETURN{} identical(v, \TRUE{}); \}(o) \end{dartCode} \rationale{ Boolean conversion is used as part of control-flow constructs and boolean expressions. Ideally, one would simply insist that control-flow decisions be based exclusively on booleans. This is straightforward in a statically typed setting. In a dynamically typed language, it requires a dynamic check. Sophisticated virtual machines can minimize the penalty involved. Alas, Dart must be compiled into Javascript. Boolean conversion allows this to be done efficiently. At the same time, this formulation differs radically from Javascript, where most numbers and objects are interpreted as \TRUE{}. Dart's approach prevents usages such \code{\IF{} (a-b) ... ; }because it does not agree with the low level conventions whereby non-null objects or non-zero numbers are treated as \TRUE{}. Indeed, there is no way to derive \TRUE{} from a non-boolean object via boolean conversion, so this kind of low level hackery is nipped in the bud. Dart also avoids the strange behaviors that can arise due to the interaction of boolean conversion with autoboxing in Javascript. A notorious example is the situation where \FALSE{} can be interpreted as \TRUE{}. In Javascript, booleans are not objects, and instead are autoboxed into objects where needed''. If \FALSE{} gets autoboxed into an object, that object can be coerced into \TRUE{} (as it is a non-null object). } \commentary{Because boolean conversion requires its parameter to be a boolean, any construct that makes use of boolean conversion will cause a dynamic type error in checked mode if the value to be converted is not a boolean. } \subsection{Strings} \label{strings} A {\em string} is a sequence of UTF-16 code units. \rationale{ This decision was made for compatibility with web browsers and Javascript. Earlier versions of the specification required a string to be a sequence of valid Unicode code points. Programmers should not depend on this distinction. } \begin{grammar} {\bf stringLiteral:}(multilineString $|$ singleLineString)+ . \end{grammar} A string can be either a sequence of single line strings or a multiline string. \begin{grammar} {\bf singleLineString:}{\escapegrammar \code{"}}' stringContentDQ* {\escapegrammar \code{"}}'; {\escapegrammar \code{'}}' stringContentSQ* {\escapegrammar \code{'}}'; r' {\escapegrammar \code{'}}' (\~{}( {\escapegrammar \code{'}}' $|$ NEWLINE ))* {\escapegrammar \code{'}}'; r' {\escapegrammar \code{"}}' (\~{}( {\escapegrammar \code{"}}' $|$ NEWLINE ))* {\escapegrammar \code{"}}' . \end{grammar} A single line string is delimited by either matching single quotes or matching double quotes. \commentary{ Hence, abc' and abc'' are both legal strings, as are He said To be or not to be'' did he not?' and He said To be or not to be' didn't he''. However This  is not a valid string, nor is this''. } \commentary{The grammar ensures that a single line string cannot span more than one line of source code, unless it includes an interpolated expression that spans multiple lines. } Adjacent %single line strings are implicitly concatenated to form a single string literal. %, and so are adjacent multiline strings, but the two forms may not be mixed. \commentary{Here is an example} \begin{dartCode} print("A string" "and then another"); // prints: A stringand then another \end{dartCode} \rationale{Dart also supports the operator + for string concatenation. The + operator on Strings requires a String argument. It does not coerce its argument into a string. This helps avoid puzzlers such as } \begin{dartCode} print("A simple sum: 2 + 2 = " + 2 + 2); \end{dartCode} \rationale{ which this prints 'A simple sum: 2 + 2 = 22' rather than 'A simple sum: 2 + 2 = 4'. However, the use the concatenation operation is still discouraged for efficiency reasons. Instead, the recommended Dart idiom is to use string interpolation. } \begin{dartCode} print("A simple sum: 2 + 2 = \\{2+2\}"); \end{dartCode} \rationale{String interpolation work well for most cases. The main situation where it is not fully satisfactory is for string literals that are too large to fit on a line. Multiline strings can be useful, but in some cases, we want to visually align the code. This can be expressed by writing smaller strings separated by whitespace, as shown here:} \begin{dartCode} 'Imagine this is a very long string that does not fit on a line. What shall we do? ' 'Oh what shall we do? ' 'We shall split it into pieces ' 'like so'. \end{dartCode} \begin{grammar} {\bf multilineString:}{\escapegrammar \texttt{"""}}' stringContentTDQ* {\escapegrammar \texttt{"""}}'; {\escapegrammar \code{'}\code{'}\code{'}}' stringContentTSQ* {\escapegrammar \code{'}\code{'}\code{'}}'; r' {\escapegrammar \texttt{"""}}' (\~{} {\escapegrammar \texttt{"""}}')* {\escapegrammar \texttt{"""}}'; r' {\escapegrammar \code{'}\code{'}\code{'}}' (\~{} {\escapegrammar \code{'}\code{'}\code{'}}')* {\escapegrammar \code{'}\code{'}\code{'}}' . {\bf ESCAPE\_SEQUENCE:} \backslash$n'; $\backslash$r'; $\backslash$f'; $\backslash$b'; $\backslash$t'; $\backslash$v'; $\backslash$x' HEX\_DIGIT HEX\_DIGIT; $\backslash$u' HEX\_DIGIT HEX\_DIGIT HEX\_DIGIT HEX\_DIGIT; $\backslash$u\{' HEX\_DIGIT\_SEQUENCE \}' . {\bf HEX\_DIGIT\_SEQUENCE:} HEX\_DIGIT HEX\_DIGIT? HEX\_DIGIT? HEX\_DIGIT? HEX\_DIGIT? HEX\_DIGIT? . \end{grammar} Multiline strings are delimited by either matching triples of single quotes or matching triples of double quotes. If the first line of a multiline string consists solely of the whitespace characters defined by the production {\em WHITESPACE} \ref{lexicalRules}), possibly prefixed by$\backslash$, then that line is ignored, including the new line at its end. \rationale{ The idea is to ignore whitespace, where whitespace is defined as tabs, spaces and newlines. These can be represented directly, but since for most characters prefixing by backslash is an identity, we allow those forms as well. } Strings support escape sequences for special characters. The escapes are: \begin{itemize} \item$\backslash$n for newline, equivalent to$\backslash$x0A. \item$\backslash$r for carriage return, equivalent to$\backslash$x0D. \item$\backslash$f for form feed, equivalent to$\backslash$x0C. \item$\backslash$b for backspace, equivalent to$\backslash$x08. \item$\backslash$t for tab, equivalent to$\backslash$x09. \item$\backslash$v for vertical tab, equivalent to$\backslash$x0B \item$\backslash$x$HEX\_DIGIT_1HEX\_DIGIT_2$, equivalent to$\backslash$u\{$HEX\_DIGIT_1HEX\_DIGIT_2$\}. \item$\backslash$u$HEX\_DIGIT_1HEX\_DIGIT_2HEX\_DIGIT_3HEX\_DIGIT_4$, equivalent to$\backslash$u\{$HEX\_DIGIT_1HEX\_DIGIT_2HEX\_DIGIT_3HEX\_DIGIT_4$\}. \item$\backslash$u\{$HEX\_DIGIT\_SEQUENCE$\} is the unicode scalar value represented by the$HEX\_DIGIT\_SEQUENCE$. It is a compile-time error if the value of the$HEX\_DIGIT\_SEQUENCE$is not a valid unicode scalar value. \item \$ indicating the beginning of an interpolated expression. \item Otherwise, $\backslash k$ indicates the character $k$ for any $k$ not in $\{n, r, f, b, t, v, x, u\}$. \end{itemize} Any string may be prefixed with the character r', indicating that it is a {\em raw string}, in which case no escapes or interpolations are recognized. It is a compile-time error if a non-raw string literal contains a character sequence of the form $\backslash$x that is not followed by a sequence of two hexadecimal digits. It is a compile-time error if a non-raw string literal contains a character sequence of the form $\backslash$u that is not followed by either a sequence of four hexadecimal digits, or by curly brace delimited sequence of hexadecimal digits. \begin{grammar} {\bf stringContentDQ:}\~{}( $\backslash$' $|$ {\escapegrammar \texttt{"}}' $|$ \$'$|$NEWLINE ); $\backslash$' \~{}( NEWLINE ); stringInterpolation . {\bf stringContentSQ:}\~{}( $\backslash$'$|${\escapegrammar \texttt{'}}'$|$\$' $|$ NEWLINE ); $\backslash$' \~{}( NEWLINE ); stringInterpolation . {\bf stringContentTDQ:}\~{}( $\backslash$' $|$ {\escapegrammar \texttt{"""}}' $|$ \$'); stringInterpolation . {\bf stringContentTSQ:}\~{}( $\backslash$'$|${\escapegrammar \code{'}\code{'}\code{'}}'$|$\$'); stringInterpolation . {\bf NEWLINE:}$\backslash$ n; $\backslash$ r . \end{grammar} All string literals implement the built-in class \code{String}. It is a compile-time error for a class to attempt to extend or implement \code{String}. Invoking the getter \code{runtimeType} on a string literal returns the \code{Type} object that is the value of the expression \code{String}. The static type of a string literal is \code{String}. \subsubsection{String Interpolation} \label{stringInterpolation} It is possible to embed expressions within non-raw string literals, such that the these expressions are evaluated, and the resulting values are converted into strings and concatenated with the enclosing string. This process is known as {\em string interpolation}. \begin{grammar} {\bf stringInterpolation:}\$' IDENTIFIER\_NO\_DOLLAR; \$' \{' expression \}' % could be top level expression, no? . \end{grammar} \commentary{The reader will note that the expression inside the interpolation could itself include strings, which could again be interpolated recursively. } An unescaped \$character in a string signifies the beginning of an interpolated expression. The \$ sign may be followed by either: \begin{itemize} \item A single identifier $id$ that must not contain the \$character. \item An expression$e$delimited by curly braces. \end{itemize} The form \code{\$id} is equivalent to the form \code{\$\{id\}}. An interpolated string \code{$s_1$\$\{$e$\}$s_2$'} is equivalent to the concatenation of the strings \code{$s_1$'}, \code{$e$.toString()} and \code{$s_2$'}. Likewise an interpolated string \code{$s_1$\$\{e\}$s_2$''} is equivalent to the concatenation of the strings \code{$s_1$''}, \code{$e$.toString()} and \code{$s_2$''}. \subsection{Symbols} \label{symbols} A {\em symbol literal} denotes the name of a declaration in a Dart program. \begin{grammar} {\bf symbolLiteral:} \#' (operator$|$(identifier ({\escapegrammar .}' identifier)*)) . \end{grammar} A symbol literal \code{\#id} where \code{id} does not begin with an underscore (Ô\code{\_}Õ) is equivalent to the expression \code{\CONST{} Symbol(ÔidÕ)}. A symbol literal \code{\#\_id} evaluates to the object that would be returned by the call \code{mirror.getPrivateSymbol(ÔidÕ)} where mirror is an instance of the class \code{LibraryMirror} defined in the library \code{dart:mirrors}, reflecting the current library. \rationale{ One may well ask what is the motivation for introducing literal symbols? In some languages, symbols are canonicalized whereas strings are not. However literal strings are already canonicalized in Dart. Symbols are slightly easier to type compared to strings and their use can become strangely addictive, but this is not nearly sufficient justification for adding a literal form to the language. The primary motivation is related to the use of reflection and a web specific practice known as minification. Minification compresses identifiers consistently throughout a program in order to reduce download size. This practice poses difficulties for reflective programs that refer to program declarations via strings. A string will refer to an identifier in the source, but the identifier will no longer be used in the minified code, and reflective code using these truing would fail. Therefore, Dart reflection uses objects of type \code{Symbol} rather than strings. Instances of \code{Symbol} are guaranteed to be stable with repeat to minification. Providing a literal form for symbols makes reflective code easier to read and write. The fact that symbols are easy to type and can often act as convenient substitutes for enums are secondary benefits. } The static type of a symbol literal is \code{Symbol}. \subsection{Lists} \label{lists} A {\em list literal} denotes a list, which is an integer indexed collection of objects. \begin{grammar} {\bf listLiteral:} \CONST{}? typeArguments? [' (expressionList ,'?)? ]' . \end{grammar} A list may contain zero or more objects. The number of elements in a list is its size. A list has an associated set of indices. An empty list has an empty set of indices. A non-empty list has the index set$\{0 \ldots n -1\}$where$n$is the size of the list. It is a runtime error to attempt to access a list using an index that is not a member of its set of indices. If a list literal begins with the reserved word \CONST{}, it is a {\em constant list literal} which is a compile-time constant (\ref{constants}) and therefore evaluated at compile-time. Otherwise, it is a {\em run-time list literal} and it is evaluated at run-time. Only run-time list literals can be mutated after they are created. Attempting to mutate a constant list literal will result in a dynamic error. It is a compile-time error if an element of a constant list literal is not a compile-time constant. It is a compile-time error if the type argument of a constant list literal includes a type parameter. \rationale{The binding of a type parameter is not known at compile-time, so we cannot use type parameters inside compile-time constants.} The value of a constant list literal \CONST{}$[e_1\ldots e_n]$is an object$a$whose class implements the built-in class$List$. The$i$th element of$a$is$v_{i+1}$, where$v_i$is the value of the compile-time expression$e_i$. The value of a constant list literal \CONST{}$[e_1 \ldots e_n]$is defined as the value of the constant list literal \CONST{}$ < \DYNAMIC{}>[e_1\ldots e_n]$. Let$list_1 =$\CONST{}$[e_{11} \ldots e_{1n}]$and$list_2 =$\CONST{}$[e_{21} \ldots e_{2n}]$be two constant list literals and let the elements of$list_1$and$list_2$evaluate to$o_{11} \ldots o_{1n}$and$o_{21} \ldots o_{2n}$respectively. Iff \code{identical($o_{1i}$,$o_{2i}$)} for$i \in 1.. n$and$V = U$then \code{identical($list_1$,$list_2$)}. \commentary{In other words, constant list literals are canonicalized.} A run-time list literal$[e_1 \ldots e_n]$is evaluated as follows: \begin{itemize} \item First, the expressions$e_1 \ldots e_n$are evaluated in order they appear in the program, yielding objects$o_1 \ldots o_n$. \item A fresh instance (\ref{generativeConstructors})$a$, of size$n$, whose class implements the built-in class$List$is allocated. \item The operator \code{[]=} is invoked on$a$with first argument$i$and second argument %The$i$th element of$a$is set to$o_{i+1}, 0 \le i < n$. \item The result of the evaluation is$a$. \end{itemize} \commentary{ Note that this document does not specify an order in which the elements are set. This allows for parallel assignments into the list if an implementation so desires. The order can only be observed in checked mode (and may not be relied upon): if element$i$is not a subtype of the element type of the list, a dynamic type error will occur when$a[i]$is assigned$o_{i-1}$. } A runtime list literal$[e_1 \ldots e_n]$is evaluated as$< \DYNAMIC{}>[e_1\ldots e_n]$. \commentary{ There is no restriction precluding nesting of list literals. It follows from the rules above that$>[[1, 2, 3], [4, 5, 6]]$is a list with type parameter$List$, containing two lists with type parameter \DYNAMIC{}. } The static type of a list literal of the form \CONST{}$ [e_1\ldots e_n]$or the form$[e_1 \ldots e_n]$is$List$. The static type a list literal of the form \CONST{}$[e_1 \ldots e_n$] or the form$[e_1\ldots e_n$] is$List< \DYNAMIC{}>$. \rationale{ It is tempting to assume that the type of the list literal would be computed based on the types of its elements. However, for mutable lists this may be unwarranted. Even for constant lists, we found this behavior to be problematic. Since compile-time is often actually runtime, the runtime system must be able to perform a complex least upper bound computation to determine a reasonably precise type. It is better to leave this task to a tool in the IDE. It is also much more uniform (and therefore predictable and understandable) to insist that whenever types are unspecified they are assumed to be the unknown type \DYNAMIC{}. } %Invoking the getter \code{runtimeType} on a list literal returns the \code{Type} object that is the value of the expression \code{List}. The static type of a list literal is \code{List}. % what about generics? \subsection{Maps} \label{maps} A {\em map literal} denotes a map object. \begin{grammar} {\bf mapLiteral:} \CONST{}? typeArguments? \{' (mapLiteralEntry (,' mapLiteralEntry)* ,'?)? \}' . {\bf mapLiteralEntry:} % identifier {\escapegrammar :}' expression; expression {\escapegrammar :}' expression . \end{grammar} A {\em map literal} consists of zero or more entries. Each entry has a {\em key} and a {\em value}. Each key and each value is denoted by an expression. If a map literal begins with the reserved word \CONST{}, it is a {\em constant map literal} which is a compile-time constant (\ref{constants}) and therefore evaluated at compile-time. Otherwise, it is a {\em run-time map literal} and it is evaluated at run-time. Only run-time map literals can be mutated after they are created. Attempting to mutate a constant map literal will result in a dynamic error. It is a compile-time error if either a key or a value of an entry in a constant map literal is not a compile-time constant. It is a compile-time error if the key of an entry in a constant map literal is an instance of a class that implements the operator$==$unless the key is a string or integer. It is a compile-time error if the type arguments of a constant map literal include a type parameter. The value of a constant map literal \CONST{}$ \{k_1:e_1\ldots k_n :e_n\}$is an object$m$whose class implements the built-in class$Map$. The entries of$m$are$u_i:v_i, i \in 1 .. n$, where$u_i$is the value of the compile-time expression$k_i$and$v_i$is the value of the compile-time expression$e_i$. The value of a constant map literal \CONST{}$\{k_1:e_1\ldots k_n :e_n\}$is defined as the value of a constant map literal \CONST{}$<\DYNAMIC{}, \DYNAMIC{}>\{k_1:e_1\ldots k_n :e_n\}$. Let$map_1 =$\CONST{}$ \{k_{11}:e_{11} \ldots k_{1n} :e_{1n}\}$and$map_2 =$\CONST{}$ \{k_{21}:e_{21} \ldots k_{2n} :e_{2n}\}$be two constant map literals. Let the keys of$map_1$and$map_2$evaluate to$s_{11} \ldots s_{1n}$and$s_{21} \ldots s_{2n}$respectively, and let the elements of$map_1$and$map_2$evaluate to$o_{11} \ldots o_{1n}$and$o_{21} \ldots o_{2n}$respectively. Iff \code{identical($o_{1i}$,$o_{2i}$)} and \code{identical($s_{1i}$,$s_{2i}$)} for$i \in 1.. n$, and$K = J, V = U$then \code{identical($map_1$,$map_2$)}. \commentary{In other words, constant map literals are canonicalized.} A runtime map literal$\{k_1:e_1\ldots k_n :e_n\}$is evaluated as follows: \begin{itemize} \item First, the expression$k_i$is evaluated yielding object$u_i$, the$e_i$is vaulted yielding object$o_i$, for$i \in 1..n$in left to right order, yielding objects$u_1, o_1\ldots u_n, o_n$. \item A fresh instance (\ref{generativeConstructors})$m$whose class implements the built-in class$Map$is allocated. \item The operator \code{[]=} is invoked on$m$with first argument$u_i$and second argument$o_i, i \in 1.. n$. \item The result of the evaluation is$m$. \end{itemize} A runtime map literal$\{k_1:e_1\ldots k_n :e_n\}$is evaluated as$<\DYNAMIC{}, \DYNAMIC{}>\{k_1:e_1\ldots k_n :e_n\}$. Iff all the keys in a map literal are compile-time constants, it is a static warning if the values of any two keys in a map literal are equal. A map literal is ordered: iterating over the keys and/or values of the maps always happens in the order the keys appeared in the source code. \commentary{ Of course, if a key repeats, the order is defined by first occurrence, but the value is defined by the last. } The static type of a map literal of the form \CONST{}$ \{k_1:e_1\ldots k_n :e_n\}$or the form$\{k_1:e_1\ldots k_n :e_n\}$is$Map$. The static type a map literal of the form \CONST{}$\{k_1:e_1\ldots k_n :e_n\}$or the form$\{k_1:e_1\ldots k_n :e_n\}$is$Map<\DYNAMIC{}, \DYNAMIC{}>$. \subsection{Throw} \label{throw} The {\em throw expression} is used to raise an exception. \begin{grammar} {\bf throwExpression:} \THROW{} expression . {\bf throwExpressionWithoutCascade:} \THROW{} expressionWithoutCascade . \end{grammar} The {\em current exception} is the last unhandled exception thrown. Evaluation of a throw expression of the form \code{\THROW{}$e$;} proceeds as follows: The expression$e$is evaluated yielding a value$v$. If$v$evaluates to \NULL{}, then a \code{NullThrownError} is thrown. Otherwise, control is transferred to the nearest dynamically enclosing exception handler (\ref{try}), with the current exception set to$v$. \commentary{ There is no requirement that the expression$e$evaluate to a special kind of exception or error object. } If the object being thrown is an instance of class \code{Error} or a subclass thereof, its \code{stackTrace} getter will return the stack trace current at the point where the the object was first thrown. The static type of a throw expression is$\bot$. \subsection{ Function Expressions} \label{functionExpressions} A {\em function literal} is an object that encapsulates an executable unit of code. \begin{grammar} {\bf functionExpression:} formalParameterList functionExpressionBody . {\bf functionExpressionBody:} ={\escapegrammar \gt}' expression; block . \end{grammar} 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} The static type of a function literal of the form$(T_1a_1, \ldots, T_na_n, [T_{n+1}x_{n+1} = d_1, \ldots, T_{n+k}x_{n+k} = d_k]) => e$is$(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$. In any case where$T_i, 1 \le i \le n+k$, is not specified, it is considered to have been specified as \DYNAMIC{}. The static type of a function literal of the form$(T_1a_1, \ldots, T_na_n, \{T_{n+1}x_{n+1} : d_1, \ldots, T_{n+k}x_{n+k} : d_k\}) => e$is$(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$. In any case where$T_i, 1 \le i \le n+k$, is not specified, it is considered to have been specified as \DYNAMIC{}. The static type of a function literal of the form$(T_1a_1, \ldots, T_na_n, [T_{n+1}x_{n+1} = d_1, \ldots, T_{n+k}x_{n+k}= d_k])\{s\}$is$(T_1 \ldots, T_n, [T_{n+1}x_{n+1}, \ldots, T_{n+k}x_{n+k}]) \rightarrow \DYNAMIC{}$. In any case where$T_i, 1 \le i \le n+k$, is not specified, it is considered to have been specified as \DYNAMIC{}. The static type of a function literal of the form$(T_1a_1, \ldots, T_na_n, \{T_{n+1}x_{n+1} : d_1, \ldots, T_{n+k}x_{n+k} : d_k\})\{s\}$is$(T_1 \ldots, T_n, \{T_{n+1}x_{n+1}, \ldots, T_{n+k}x_{n+k}\}) \rightarrow \DYNAMIC{}$. In any case where$T_i, 1 \le i \le n+k$, is not specified, it is considered to have been specified as \DYNAMIC{}. %** Now that declared return types are precluded, do we need some better return type rule for (x){s} and friends? \subsection{ This} \label{this} The reserved word \THIS{} denotes the target of the current instance member invocation. \begin{grammar} {\bf thisExpression:} \THIS{} . \end{grammar} The static type of \THIS{} is the interface of the immediately enclosing class. \commentary{ We do not support self-types at this point. } It is a compile-time error if \THIS{} appears in a top-level function or variable initializer, in a factory constructor, or in a static method or variable initializer, or in the initializer of an instance variable. \subsection{ Instance Creation} \label{instanceCreation} Instance creation expressions invoke constructors to produce instances. %It is a compile-time error if any of the type arguments to a constructor of a generic type invoked by a new expression or a constant object expression do not denote types in the enclosing lexical scope. %It is a compile-time error if a constructor of a non-generic type invoked by a new expression or a constant object expression is passed any type arguments. It is a compile-time error if a constructor of a generic type with$n$type parameters invoked by a new expression or a constant object expression is passed$m$type arguments where$m \ne n$, or if any of its type arguments is misconstructed (\ref{parameterizedTypes}). It is a static type warning if the type$T$in an instance creation expression of one of the forms \NEW{}$T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$, \NEW{}$T(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$, \CONST{}$T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$, \CONST{}$T(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$is malformed (\ref{dynamicTypeSystem}) or malbounded (\ref{parameterizedTypes}). %any of the type arguments to a constructor of a generic type$G$invoked by a new expression or a constant object expression are not subtypes of the bounds of the corresponding formal type parameters of$G$. \subsubsection{ New} \label{new} The {\em new expression} invokes a constructor (\ref{constructors}). \begin{grammar} {\bf newExpression:} \NEW{} type ({\escapegrammar .}' identifier)? arguments . \end{grammar} Let$e$be a new expression of the form \NEW{}$T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$or the form \NEW{}$T(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$. %It is a runtime type error if %the type$T$is malformed. %It is a static warning if$T$is a malformed type. %not a class accessible in the current scope, optionally followed by type arguments. If$T$is a class or parameterized type accessible in the current scope then: \begin{itemize} \item If$e$is of the form \NEW{}$T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$it is a static warning if$T.id$is not the name of a constructor declared by the type$T$. If$e$is of the form \NEW{}$T(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$it is a static warning if the type$T$does not declare a constructor with the same name as the declaration of$T$. \end{itemize} If$T$is a parameterized type (\ref{parameterizedTypes})$S$, let$R = S$. %It is a %compile-time CHANGED %runtime type %error if$S$is not a generic (\ref{generics}) type with$m$type parameters. If$T$is not a parameterized type, let$R = T$. Furthermore, if$e$is of the form \NEW{}$T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$then let$q$be the constructor$T.id$, otherwise let$q$be the constructor$T$. If$R$is a generic with$l = m$type parameters then \begin{itemize} \item$T$is not a parameterized type, then for$ i \in 1 .. l$, let$V_i = \DYNAMIC{}$. \item If$T$is a parameterized type then let$V_i = U_i$for$ i \in 1 .. m$. \end{itemize} If$R$is a generic with$l \ne m$type parameters then for$ i \in 1 .. l$, let$V_i = \DYNAMIC{}$. In any other case, let$V_i = U_i$for$ i \in 1 .. m$. Evaluation of$e$proceeds as follows: First, the argument list$(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$is evaluated. Then, if$q$is a non-factory constructor of an abstract class then an \code{AbstractClassInstantiationError} is thrown. If$T$is malformed or if$T$is a type variable a dynamic error occurs. In checked mode, if$T$or any of its superclasses is malbounded a dynamic error occurs. Otherwise, if$q$is not defined or not accessible, a \code{NoSuchMethodError} is thrown. If$q$has less than$n$positional parameters or more than$n$required parameters, or if$q$lacks any of the keyword parameters$\{ x_{n+1}, \ldots, x_{n+k}\}$a \code{NoSuchMethodError} is thrown. Otherwise, if$q$is a generative constructor (\ref{generativeConstructors}), then: %Let$T_i$be the type parameters of$R$(if any) and let$B_i$be the bound of$T_i, 1 \le i \le l$. %In checked mode, it is a dynamic type error if$V_i$is not a subtype of$[V_1, \ldots, V_l/T_1, \ldots, T_l]B_i, i \in 1.. l$. \commentary{Note that it this point we are assured that the number of actual type arguments match the number of formal type parameters.} A fresh instance (\ref{generativeConstructors}),$i$, of class$R$is allocated. For each instance variable$f$of$i$, if the variable declaration of$f$has an initializer expression$e_f$, then$e_f$is evaluated to an object$o_f$and$f$is bound to$o_f$. Otherwise$f$is bound to \NULL{}. \commentary{ Observe that \THIS{} is not in scope in$e_f$. Hence, the initialization cannot depend on other properties of the object being instantiated. } Next,$q$is executed with \THIS{} bound to$i$, the type parameters (if any) of$R$bound to the actual type arguments$V_1, \ldots, V_l$and the formal parameter bindings that resulted from the evaluation of the argument list. The result of the evaluation of$e$is$i$. Otherwise,$q$is a factory constructor (\ref{factories}). Then: %Let$T_i$be the type parameters of$R$(if any) and let$B_i$be the bound of$T_i, 1 \le i \le l$. %In checked mode, it is a dynamic type error if$V_i$is not a subtype of$[V_1, \ldots, V_l/T_1, \ldots, T_l]B_i, i \in 1.. l$. If$q$is a redirecting factory constructor of the form$T(p_1, \ldots, p_{n+k}) = c;$or of the form$T.id(p_1, \ldots, p_{n+k}) = c;$then the result of the evaluation of$e$is equivalent to evaluating the expression$[V_1, \ldots, V_m/T_1, \ldots, T_m]($\code{\NEW{}$c(a_1, \ldots, a_n, x_{n+1}: a_{n+1}, \ldots, x_{n+k}: a_{n+k}))$}. Otherwise, the body of$q$is executed with respect to the bindings that resulted from the evaluation of the argument list and the type parameters (if any) of$q$bound to the actual type arguments$V_1, \ldots, V_l$resulting in an object$i$. The result of the evaluation of$e$is$i$. It is a static warning if$q$is a constructor of an abstract class and$q$is not a factory constructor. \commentary{The above gives precise meaning to the idea that instantiating an abstract class leads to a warning. A similar clause applies to constant object creation in the next section. } \rationale{In particular, a factory constructor can be declared in an abstract class and used safely, as it will either produce a valid instance or lead to a warning inside its own declaration. } The static type of an instance creation expression of either the form \NEW{}$T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$or the form \NEW{}$T(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$is$T$. It is a static warning if the static type of$a_i, 1 \le i \le n+ k$may not be assigned to the type of the corresponding formal parameter of the constructor$T.id$(respectively$T$). \subsubsection{ Const} \label{const} A {\em constant object expression} invokes a constant constructor (\ref{constantConstructors}). \begin{grammar} {\bf constObjectExpression:} \CONST{} type ('{\escapegrammar .}' identifier)? arguments . \end{grammar} Let$e$be a constant object expression of the form \CONST{}$T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$or the form \CONST{}$T(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$. It is a compile-time error if$T$does not denote a class accessible in the current scope. \commentary{In particular,$T$may not be a type variable.} If$T$is a parameterized type, it is a compile-time error if$T$includes a type variable among its type arguments. If$e$is of the form \CONST{}$T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$it is a compile-time error if$T.id$is not the name of a constant constructor declared by the type$T$. If$e$is of the form \CONST{}$T(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$it is a compile-time error if the type$T$does not declare a constant constructor with the same name as the declaration of$T$. In all of the above cases, it is a compile-time error if$a_i, i\in 1 .. n + k$, is not a compile-time constant expression. %If$T$is a parameterized type (\ref{parameterizedTypes})$S$, let$R = S$. It is a compile-time error if$T$is is malformed. If$T$is not a parameterized type, let$R = T$. %Finally, % If$T$is a generic with$l$retype parameters, then for all$ i \in 1 .. l$, let$V_i = \DYNAMIC{}$. Evaluation of$e$proceeds as follows: First, if$e$is of the form \CONST{}$T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$then let$i$be the value of the expression \NEW{}$T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$. Otherwise,$e$must be of the form \CONST{}$T(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$, in which case let$i$be the result of evaluating \NEW{}$T(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$. Then: \begin{itemize} \item If during execution of the program, a constant object expression has already evaluated to an instance$j$of class$R$with type arguments$V_i, 1 \le i \le m$, then: \begin{itemize} \item For each instance variable$f$of$i$, let$v_{if}$be the value of the field$f$in$i$, and let$v_{jf}$be the value of the field$f$in$j$. If \code{identical($v_{if}$,$v_{jf}$)} for all fields$f$in$i$, then the value of$e$is$j$, otherwise the value of$e$is$i$. \end{itemize} \item Otherwise the value of$e$is$i$. \end{itemize} \commentary{ In other words, constant objects are canonicalized. In order to determine if an object is actually new, one has to compute it; then it can be compared to any cached instances. If an equivalent object exists in the cache, we throw away the newly created object and use the cached one. Objects are equivalent if they have identical fields and identical type arguments. Since the constructor cannot induce any side effects, the execution of the constructor is unobservable. The constructor need only be executed once per call site, at compile-time. } The static type of a constant object expression of either the form \CONST{}$T.id(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$or the form \CONST{}$T(a_1, \ldots , a_n, x_{n+1}: a_{n+1}, \ldots , x_{n+k}: a_{n+k})$is$T$. It is a static warning if the static type of$a_i, 1 \le i \le n+ k$may not be assigned to the type of the corresponding formal parameter of the constructor$T.id$(respectively$T$). It is a compile-time error if evaluation of a constant object results in an uncaught exception being thrown. \commentary{ To see how such situations might arise, consider the following examples: } \begin{dartCode} \CLASS{} A \{ \FINAL{} x; \CONST{} A(p): x = p * 10; \} \CONST{} A("x"); // compile-time error \CONST{} A(5); // legal \CLASS{} IntPair \{ \CONST{} IntPair(\THIS{}.x, \THIS{}.y); \FINAL{} int x; \FINAL{} int y; \OPERATOR *(v)$=>$\NEW{} IntPair(x*v, y*v); \} \CONST{} A(\CONST{} IntPair(1,2)); // compile-time error: illegal in a subtler way \end{dartCode} \commentary{ Due to the rules governing constant constructors, evaluating the constructor \code{A()} with the argument \code{''x''} or the argument \code{\CONST{} IntPair(1, 2)} would cause it to throw an exception, resulting in a compile-time error. } Given an instance creation expression of the form \CONST{}$q(a_1, \ldots , a_n)$it is a static warning if$q$is a constructor of an abstract class (\ref{abstractInstanceMembers}) but$q$is not a factory constructor. \subsection{ Spawning an Isolate} \label{spawningAnIsolate} Spawning an isolate is accomplished via what is syntactically an ordinary library call, invoking one of the functions \code{spawnUri()} or \code{spawnFunction()}defined in the \code{dart:isolate} library. However, such calls have the semantic effect of creating a new isolate with its own memory and thread of control. An isolate's memory is finite, as is the space available to its thread's call stack. It is possible for a running isolate to exhaust its memory or stack, resulting in a run-time error that cannot be effectively caught, which will force the isolate to be suspended. \commentary{ As discussed in section \ref{errorsAndWarnings}, the handling of a suspended isolate is the responsibility of the embedder. } \subsection{ Property Extraction} \label{propertyExtraction} {\em Property extraction} allows for a member of an object to be concisely extracted from the object. If$e$is an expression that evaluates to an object$o$, and if$m$is the name of a concrete method member of$e$, then$e.m$is defined to be equivalent to: \begin{itemize} %\item$(r_1, \ldots, r_n)\{\RETURN{}o.m(r_1, \ldots, r_n);\}$if$m$has only required parameters$r_1, \ldots r_n$. %\item$(r_1, \ldots, r_n, rest)\{returno.m(r_1, \ldots, r_n, rest);\}$if$m$has required parameters$r_1, \ldots r_n$, and a rest parameter$rest$. %\item % so the issue is that o is not an expression, but we don't want to bind to e, as its evaluation % could have side effects, result in different objects at different times etc. % so we use u, where u is a fresh final variable bound to o % \item$(r_1, \ldots, r_n, \{p_1 : d_1, \ldots , p_k : d_k\})\{$\RETURN{}$u.m(r_1, \ldots, r_n, p_1: p_1, \ldots, p_k: p_k);\}$if$m$has required parameters$r_1, \ldots, r_n$, and named parameters$p_1, \ldots, p_k$with defaults$d_1, \ldots, d_k$. \item$(r_1, \ldots, r_n, [p_1 = d_1, \ldots , p_k = d_k])\{$\RETURN{}$u.m(r_1, \ldots, r_n, p_1, \ldots, p_k);\}$if$m$has required parameters$r_1, \ldots, r_n$, and optional positional parameters$p_1, \ldots, p_k$with defaults$d_1, \ldots, d_k$. \end{itemize} where$u$is a fresh final variable bound to$o$, except that: \begin{enumerate} \item iff \code{identical($o_1, o_2$)} then \cd{$o_1.m$==$o_2.m$}. \item The static type of the property extraction is the static type of function$T.m$, where$T$is the static type of$e$, if$T.m$is defined. Otherwise the static type of$e.m$is \DYNAMIC{}. \end{enumerate} \commentary{ There is no guarantee that \cd{identical($o_1.m, o_2.m$)}. Dart implementations are not required to canonicalize these or any other closures. } % local functions that have a closure extracted are always different \rationale{ The special treatment of equality in this case facilitates the use of extracted property functions in APIs where callbacks such as event listeners must often be registered and later unregistered. A common example is the DOM API in web browsers. } Otherwise %, if$m$is the name of a getter (\ref{getters}) member of$e$(declared implicitly or explicitly) then$e.m\$ is treated as a getter invocation (\ref{getterInvocation})).