-
Notifications
You must be signed in to change notification settings - Fork 205
/
dartLangSpec.tex
19187 lines (16328 loc) · 715 KB
/
dartLangSpec.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
\documentclass[makeidx]{article}
\usepackage{xspace}
\usepackage{epsfig}
\usepackage{xcolor}
\usepackage{syntax}
\usepackage[fleqn]{amsmath}
\usepackage{amssymb}
\usepackage{semantic}
\usepackage{dart}
\usepackage{hyperref}
\usepackage{lmodern}
\usepackage[T1]{fontenc}
\usepackage{makeidx}
\makeindex
\title{Dart Programming Language Specification\\
{5th edition draft}\\
{\large Version 2.3.0-dev}}
\author{}
% For information about Location Markers (and in particular the
% commands \LMHash and \LMLabel), see the long comment at the
% end of this file.
% CHANGES
% =======
%
% Significant changes to the specification.
%
% 2.7
% - Rename non-terminals `<...Definition>` to `<...Declaration>` (e.g., it is
% 'class declaration' everywhere, so `<classDefinition>` is inconsistent).
% - Clarify that <libraryDeclaration> and <partDeclaration> are the
% start symbols of the grammar.
% - Clarify the notion of being 'noSuchMethod forwarded': `m` is indeed
% noSuchMethod forwarded if an implementation of `m` is inherited, but
% it does not have the required signature.
% - Clarify static checks on `yield` and `yield*` to explicitly ensure that
% assignability is enforced per element.
% - Update whitelist for expressions of type void to include `await e`,
% consistent with decision in SDK issue #33415.
% - Re-adjust `yield*` rules: Per-element type checks are not supported,
% the given Iterable/Stream must have a safe element type.
% - Clarify that an expression of type `X extends T` can be invoked when
% `T` is a function type, plus other similar cases.
%
% 2.6
% - Specify static analysis of a "callable object" invocation (where
% the callee is an instance of a class that has a `call` method).
% - Specify that <libraryImport> string literals cannot use string
% interpolation; specify that it is a dynamic error for `loadLibrary`
% to load a different library than the one which was used for
% compile-time checks.
% - Specify that a constant expression `e.length` can only invoke an instance
% getter (in particular, it cannot execute/tear-off an extension member);
% similar changes were made for several operators.
% - Specify the type arguments of the fields of an `Invocation` received by
% `noSuchMethod`, when invoked in response to a failed instance member
% invocation.
%
% 2.4
% - Clarify the section 'Exports'.
% - Update grammar rules for <declaration>, to support `static late final`
% variables with no initializer; for several top-level declarations,
% to correct the existence and placement of <metadata>; for
% <assignableSelectorPart>, to simplify the grammar (preserving the
% derivable terms); for <topLevelDeclaration>, to allow top-level final
% and const variables with no type, and to allow `late final` top-level
% variables, to allow `late` on a top-level variable declaration; and
% adding <namedParameterType> to allow `required` parameters.
% - Make lexical identifier lookups use the rules for 'Identifier Reference'
% consistently; that is, always look up `id` as well as `id=`, and commit
% to the kind of declaration found by that lookup.
% - Specify the signature of the `call` method of a function object.
% - Add the rule that it is an error for a type variable of a class to occur
% in a non-covariant position in a superinterface.
% - Correct several grammar rules, including: added <functionExpressionBody> (to
% avoid semicolon in <functionBody>), adjusted <importSpecification>.
% - Revise section on cascades. Now uses compositional grammar, and
% specifies static type, compile-time errors, and includes `?..'.
% - Correct the grammar and lexical rules for string literals.
% - Change specification of `await` to be type-safe, avoiding cases like:
% FutureOr<Future<S>> ffs = Future<S>.value(s);
% Future<S> fs = await ffs;
%
% 2.3
% - Add requirement that the iterator of a for-in statement must have
% type `Iterator`.
% - Clarify which constructors are covered by the section 'Constant
% Constructors' and removed confusing redundancy in definiton of
% potentially constant expressions.
% - Integrate the feature specification of collection literal elements
% (aka UI-as-code).
%
% 2.2
% - Specify whether the values of literal expressions override Object.==.
% - Allow Type objects as case expressions and const map keys.
% - Introduce set literals.
% - Specify that a getter/setter and a method with the same basename is
% an error, also in the case where a class obtains both from its
% superinterfaces.
% - Specify the Dart 2.0 rule that you cannot implement, extend or mix-in
% Function.
% - Generalize specification of type aliases such that they can denote any
% type, not just function types.
% - Clarify that 'Constant Constructors' is concerned with non-redirecting
% generative constructors only.
%
% 2.1
% - Remove 64-bit constraint on integer literals compiled to JavaScript numbers.
% - Allow integer literals in a double context to evaluate to a double value.
% - Specify dynamic error for a failing downcast in redirecting factory
% constructor invocation.
% - Specify that type arguments passed in a redirecting factory constructor
% declaration must be taken into account during static checks.
% - Disallow any expression statement starting with `{`, not just
% those that are map literals.
% - Define a notion of lookup that is needed for super invocations, adjust
% specification of super invocations accordingly.
% - Specify that it is a dynamic error to initialize a non-static variable
% with an object that does not have the declared type (e.g., a failed cast).
% - Specify for constructor initializers that target variable must exist and
% the initializing expression must have a type which is assignable to its
% type.
% - Specify for superinitializers that the target constructor must exist and
% the argument part must have a matching shape and pass type and value
% arguments satisfying the relevant constraints.
% - Reword rules about abstract methods and inheritance to use 'class
% interface'.
% - Specify that it is an error for a concrete class with no non-trivial
% \code{noSuchMethod} to not have a concrete declaration for some member
% in its interface, or to have one which is not a correct override.
% - Use \ref{bindingActualsToFormals} in 3 locations, eliminating 2 extra
% copies of nearly the same text.
% - Add figure in \ref{bindingActualsToFormals} for improved readability.
% - Introduce a notion of lookup which is needed for superinvocations.
% - Use new lookup concept to simplify specification of getter, setter, method
% lookup.
% - Introduce several `Case<SomeTopic>` markers in order to improve
% readability.
% - Reorganize several sections to specify static analysis first and then
% dynamic semantics; clarify many details along the way. The sections are:
% \ref{variables}, \ref{new}, \ref{const}, \ref{bindingActualsToFormals},
% \ref{unqualifiedInvocation}, \ref{functionExpressionInvocation},
% \ref{superInvocations}, \ref{assignment}, \ref{compoundAssignment},
% \ref{localVariableDeclaration}, and \ref{return}.
% - Corrected error involving multiple uses of the same part in the same
% program such that it takes exports into account.
% - Eliminate all references to checked and production mode, Dart 2 does
% not have modes.
% - Integrate feature specification on noSuchMethod forwarders.
% - Specify that bound satisfaction in generic type alias type parameters
% must imply bound satisfaction everywhere in the body.
% - Specify that super-bounded generic type alias applications must trigger
% a well-boundedness check on all types occurring in the denoted type.
% - Corrected corner case of rules for generation of noSuchMethod forwarders.
% - Integrate feature specification on parameters that are
% covariant-by-declaration.
% - Integrate feature specification on parameters that are
% covariant-by-class.
% - Correct section 'Type of a function', allowing for adjustments needed
% for rules related to covariant parameters.
% - Specified the dynamic type of function objects in several contexts, such
% that the special treatment of covariant parameters can be mentioned.
% - Specified what it means for an override relation to be correct, thus
% adding the parts that are not captured by a function type subtype check.
% - Introduced the notion of member signatures, specified that they are the
% kind of entity that a class interface contains.
% - Corrected super-boundedness check to take variance into account at the
% top level.
%
% 2.0
% - Don't allow functions as assert test values.
% - Start running "async" functions synchronously.
% - It is a static warning and dynamic error to assign to a final local.
% - Specify what "is equivalent to" means.
% - Remove @proxy.
% - Don't specify the exact object used for empty positionalArguments and
% namedArguments on Invocation.
% - Remove the, now unnecessary, handling of invalid overrides of noSuchMethod.
% - Add >>> as overridable operator.
% - If initializing formal has type annotation, require subtype of field type.
% - Constant `==` operations now also allowed if just one operand is null.
% - Make flatten not be recursive.
% - Disallow implementing two instantiations of the same generic interface.
% - Update "FutureOr" specification for Dart 2.0.
% - Require that a top-level "main" declaration is a valid script-entry
% function declaration.
% - State that the return type of a setter or []= is void when not specified.
% - Clarify that "noSuchMethod" must be implemented, not just redeclared
% abstractly, to eliminate certain diagnostic messages.
% - Add generic functions and methods to the language.
% - Don't cause warning if a non-system library import shadows a system library.
% - Update mixin application forwarding constructors to correctly handle
% optional parameters and const constructors.
% - Specify `call` for Dart 2 (no function type given to enclosing class).
% - Clarify that an identifier reference denoting a top-level, static, or
% local function evaluates to the closurization of that declaration.
% - Make `mixin` and `interface` built-in identifiers.
% - Make `async` *not* a reserved word inside async functions.
% - Add 'Class Member Conflicts', simplifying and adjusting rules about
% member declaration conflicts beyond "`n` declared twice in one scope".
% - Specify that integer literals are limited to signed 64-bit values,
% and that the `int` class is intended as signed 64-bit integer, but
% that platforms may differ.
% - Specify variance and super-bounded types.
% - Introduce `subterm` and `immediate subterm`.
% - Introduce `top type`.
% - Specify configurable imports.
% - Specify the dynamic type of the Iterable/Future/Stream returned from
% invocations of functions marked sync*/async/async*.
% - Add appendix listing the major differences between 64-bit integers
% and JavaScript integers.
% - Remove appendix on naming conventions.
% - Make it explicit that "dynamic" is exported from dart:core.
% - Remove "boolean conversion". It's just an error to not be a bool.
% - Adjust cyclic subtype prevention rule for type variables.
% - Clarify that it is an error to use FutureOr<T> as a superinterface etc.
% - Eliminate the notion of static warnings, all program faults are now errors.
% - It is no longer an error for a getter to have return type `void`.
% - Specify that each redirection of a constructor is checked, statically and
% dynamically.
% - Specify that it is an error for a superinitializer to occur anywhere else
% than at the end of an initializer list.
% - Update the potentially/compile-time constant expression definitions
% so that "potentially constant" depends only on the grammar, not the types
% of sub-expressions.
% - Make `==` recognize `null` and make `&&` and `||` short-circuit in constant
% expressions.
% - Add `as` and `is` expressions as constant expressions
% - Make `^`, `|` and `&` operations on `bool` constant operations.
% - Integrate subtyping.md. This introduces the Dart 2 rules for subtyping,
% which in particular means that the notion of being a more specific type
% is eliminated, and function types are made contravariant in their
% parameter types.
% - Integrate instantiation to bound. This introduces the notions of raw
% types, the raw-depends relation, and simple bounds; and it specifies
% the algorithm which is used to expand a raw type (e.g., `C`) to a
% parameterized type (e.g., `C<int>`).
% - Integrate invalid_returns.md. This replaces the rules about when it is
% an error to have `return;` or `return e;` in a function.
% - Integrate generalized-void.md. Introduces syntactic support for using
% `void` in many new locations, including variable type annotations and
% actual type arguments; also adds errors for using values of type `void`.
% - Integrate implicit_creation.md, specifying how some constant expressions
% can be written without `const`, and all occurrences of `new` can be
% omitted.
%
% 1.15
% - Change how language specification describes control flow.
% - Object initialization now specifies initialization order correctly.
% - Specifies that leaving an await-for loop must wait for the subscription
% to be canceled.
% - An await-for loop only pauses the subscription if it does something async.
% - Assert statements allows a "message" operand and a trailing comma.
% - The Null type is now considered a subtype of all types in most cases.
% - Specify what NEWLINE means in multiline strings.
% - Specified the FutureOf type.
% - Asserts can occur in initializer lists.
%
% 1.14
% - The call "C()" where "C" is a class name, is a now compile-time error.
% - Changed description of rewrites that depended on a function literal.
% In many cases, the rewrite wasn't safe for asynchronous code.
% - Removed generalized tear-offs.
% - Allow "rethrow" to also end a switch case. Allow braces around switch cases.
% - Allow using '=' as default-value separator for named parameters.
% - Make it a compile-time error if a library includes the same part twice.
% - Now more specific about the return types of sync*/async/async* functions
% in relation to return statements.
% - Allow Unicode surrogate values in String literals.
% - Make an initializing formal's value accessible in the initializer list.
% - Allow any expression in assert statements (was only conditionalExpression).
% - Allow trailing commas in argument and parameter lists.
%
% 1.11 - ECMA 408 - 4th Edition
% - Specify that potentially constant expressions must be valid expressions
% if the parameters are non-constant.
% - Make "??" a compile-time constant operator.
% - Having multiple unnamed libraries no longer causes warnings.
% - Specify null-aware operators for static methods.
%
% 1.10
% - Allow mixins to have super-classes and super-calls.
% - Specify static type checking for the implicit for-in iterator variable.
% - Specify static types for a number of expressions where it was missing.
% - Make calls on the exact type "Function" not cause warnings.
% - Specify null-aware behavior of "e?.v++" and similar expressions.
% - Specify that `package:` URIs are treated in an implementation dependent way.
% - Require warning if for-in is used on object with no "iterator" member.
%
% 1.9 - ECMA-408 - 3rd Edition
%
\begin{document}
\maketitle
\tableofcontents
\newpage
\pagestyle{myheadings}
\markright{Dart Programming Language Specification}
% begin Ecma boilerplate
\section{Scope}
\LMLabel{ecmaScope}
\LMHash{}%
This Ecma standard specifies the syntax and semantics of the Dart programming language.
It does not specify the APIs of the Dart libraries except where those library elements are essential to the correct functioning of the language itself (e.g., the existence of class \code{Object} with methods such as \code{noSuchMethod}, \code{runtimeType}).
\section{Conformance}
\LMLabel{ecmaConformance}
\LMHash{}%
A conforming implementation of the Dart programming language must provide and support all the APIs (libraries, types, functions, getters, setters, whether top-level, static, instance or local) mandated in this specification.
\LMHash{}%
A conforming implementation is permitted to provide additional APIs,
but not additional syntax,
except for experimental features.
\section{Normative References}
\LMLabel{ecmaNormativeReferences}
\LMHash{}%
The following referenced documents are indispensable for the application of this document.
For dated references, only the edition cited applies.
For undated references, the latest edition of the referenced document (including any amendments) applies.
\begin{enumerate}
\item
The Unicode Standard, Version 5.0, as amended by Unicode 5.1.0, or successor.
\item
Dart API Reference, https://api.dartlang.org/
\end{enumerate}
\section{Terms and Definitions}
\LMLabel{ecmaTermsAndDefinitions}
\LMHash{}%
Terms and definitions used in this specification are given in the body of the specification proper.
Such terms are highlighted in italics when they are introduced, e.g., `we use the term \NoIndex{verbosity} to refer to the property of excess verbiage',
and add a marker in the margin.
% End Ecma Boilerplate
\section{Notation}
\LMLabel{notation}
\LMHash{}%
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}
\LMHash{}%
Reserved words and built-in identifiers (\ref{identifierReference}) appear in {\bf bold}.
\commentary{
Examples would be \SWITCH{} or \CLASS{}.
}
\LMHash{}%
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}\color{commentaryColor}
<aProduction> ::= <anAlternative>
\alt <anotherAlternative>
\alt <oneThing> <after> <another>
\alt <zeroOrMoreThings>*
\alt <oneOrMoreThings>+
\alt <anOptionalThing>?
\alt (<some> <grouped> <things>)
\alt \gtilde{}<notAThing>
\alt `aTerminal'
\alt <A\_LEXICAL\_THING>
\end{grammar}
\LMHash{}%
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.
\LMHash{}%
Productions are embedded, as much as possible, in the discussion of the constructs they represent.
\LMHash{}%
A \Index{term} is a syntactic construct.
It may be considered to be a piece of text which is derivable in the grammar,
and it may be considered to be a tree created by such a derivation.
An \Index{immediate subterm} of a given term $t$ is a syntactic construct
which corresponds to an immediate subtree of $t$ considered as a derivation tree.
A \Index{subterm} of a given term $t$ is $t$,
or an immediate subterm of $t$,
or a subterm of an immediate subterm of $t$.
\LMHash{}%
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.
\LMHash{}%
For $j \in 1 .. n$,
let $y_j$ be an atomic syntactic entity (like an identifier),
$x_j$ a composite syntactic entity (like an expression or a type),
and $E$ again a composite syntactic entity.
The notation
\IndexCustom{$[x_1/y_1, \ldots, x_n/y_n]E$}{[x1/y1, ..., xn/yn]E@$[x/y\ldots]E$}
then denotes a copy of $E$
in which each occurrence of $y_i, 1 \le i \le n$ has been replaced by $x_i$.
\LMHash{}%
This operation is also known as \Index{substitution},
and it is the variant that avoids capture.
That is, when $E$ contains a construct that introduces $y_i$ into a nested scope for some $i \in 1 .. n$,
the substitution will not replace $y_i$ in that scope.
Conversely, if such a replacement would put an identifier \id{} (a subterm of $x_i$) into a scope where \id{} is declared,
the relevant declarations in $E$ are systematically renamed to fresh names.
\commentary{
In short, capture freedom ensures that the ``meaning'' of each identifier is preserved during substitution.
}
\LMHash{}%
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$).
\LMHash{}%
The specifications of operators often involve statements such as
\code{$x$ \metavar{op} $y$}
is equivalent to the method invocation
\IndexCustom{\rm\code{$x$.\metavar{op}($y$)}}{x.op(y)@\code{$x$.\metavar{op}($y$)}}.
Such specifications should be understood as a shorthand for:
\begin{itemize}
\item
$x$ $op$ $y$ is equivalent to the method invocation
\code{$x$.\metavar{op'}($y$)},
assuming the class of $x$ actually declared a non-operator method named $op'$
defining the same function as the operator $op$.
\end{itemize}
\rationale{
This circumlocution is required because
{\rm\code{$x$.\metavar{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.
}
\LMHash{}%
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.
\LMHash{}%
When the specification refers to a
\IndexCustom{fresh variable}{variable!fresh},
it means a local variable with a name that doesn't occur anywhere
in the current program.
When the specification introduces a fresh variable bound to an object,
the fresh variable is implicitly bound in a surrounding scope.
\LMHash{}%
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, respectively, the root of the class hierarchy and
the reification of run-time types.
%
It would be possible to declare, e.g.,
a local variable named \code{Object},
so it is generally incorrect to assume that
the name \code{Object} will actually resolve to said core class.
However, we will generally omit mentioning this, for brevity.%
}
%% TODO(eernst): We need to get rid of the concept of `is equivalent to`,
%% cf. language issue https://github.com/dart-lang/language/issues/227.
%% In this CL the phrase `treated as` has been introduced in a few places,
%% and the above-mentioned issue 227 will give rise to a complete revision
%% of this aspect of this document. In particular, the next paragraph will
%% be deleted.
\LMHash{}%
When the specification says that one piece of syntax \Index{is equivalent to}
another piece of syntax, it means that it is equivalent in all ways,
and the former syntax should generate the same compile-time errors
and have the same run-time behavior as the latter, if any.
\commentary{%
Error messages, if any, should always refer to the original syntax.%
}
If execution or evaluation of a construct is said to be
equivalent to execution or evaluation of another construct,
then only the run-time behavior is equivalent,
and compile-time errors apply only for the original syntax.
\LMHash{}%
When the specification says that one piece of syntax $s$ is
\Index{treated as}
another piece of syntax $s'$,
it means that the static analysis of $s$ is the static analysis of $s'$
(\commentary{in particular, exactly the same compile-time errors occur}).
Moreover, if $s$ has no compile-time errors then
the behavior of $s$ at run time is exactly the behavior of $s'$.
\rationale{%
Error \emph{messages}, if any, should always refer to the original syntax $s$.%
}
\commentary{%
In short, whenever $s$ is treated as $s'$,
the reader should immediately switch to the section about $s'$
in order to get any further information about
the static analysis and dynamic semantics of $s$.%
}
\rationale{%
The notion of being `treated as' is similar to the notion of syntactic sugar:
``$s$ is treated as $s'$''
could as well have been worded
``$s$ is desugared into $s'$''.
Of course, it should then actually be called ``semantic sugar'',
because the applicability of the transformation and the construction of $s'$
may rely on information from static analysis.
The point is that we only specify the static analysis and dynamic semantics
of a core language which is a subset of Dart
(just slightly smaller than Dart),
and desugaring transforms any given Dart program to
a program in that core language.
This helps keeping the language specification consistent and comprehensible,
because it shows directly
that some language features are introducing essential semantics,
and others are better described as mere abbreviations of existing constructs.%
}
\section{Overview}
\LMLabel{overview}
\LMHash{}%
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.
\LMHash{}%
Dart programs may be statically checked.
Programs with compile-time errors do not have a specified dynamic semantics.
This specification makes no attempt to answer additional questions
about a library or program at the point
where it is known to have a compile-time error.
\commentary{
However, tools may choose to support execution of some programs with errors.
For instance, a compiler may compile certain constructs with errors such that
a dynamic error will be raised if an attempt is made to
execute such a construct,
or an IDE integrated runtime may support opening
an editor window when such a construct is executed,
allowing developers to correct the error.
It is expected that such features would amount to a natural extension of the
dynamic semantics of Dart as specified here, but, as mentioned,
this specification makes no attempt to specify exactly what that means.
}
\LMHash{}%
As specified in this document,
dynamic checks are guaranteed to be performed in certain situations,
and certain violations of the type system throw exceptions at run time.
\commentary{
An implementation is free to omit such checks whenever they are
guaranteed to succeed, e.g., based on results from the static analysis.
}
\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 run time
and may always be queried by dynamic typechecking constructs
(the analogs of instanceOf, casts, typecase etc.\ in other languages).
Reified type information includes
access to instances of class \code{Type} representing types,
the run-time type (aka class) of an object,
and the actual values of type parameters
to constructors and generic function invocations.
\item
Type annotations declare the types of
variables and functions (including methods and constructors).
\item
%% TODO(eernst): Change when integrating instantiate-to-bounds.md.
Type annotations may be omitted, in which case they are generally
filled in with the type \DYNAMIC{}
(\ref{typeDynamic}).
\end{enumerate}
}
%% TODO(eernst): Update when we add inference.
\commentary{
Dart as implemented includes extensive support for inference of omitted types.
This specification makes the assumption that inference has taken place,
and hence inferred types are considered to be present in the program already.
However, in some cases no information is available
to infer an omitted type annotation,
and hence this specification still needs to specify how to deal with that.
A future version of this specification will also specify type inference.
}
\LMHash{}%
Dart programs are organized in a modular fashion into
units called \NoIndex{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.
}
\LMHash{}%
A dart program execution may occur with assertions enabled or disabled.
The method used to enable or disable assertions is implementation specific.
\subsection{Scoping}
\LMLabel{scoping}
\LMHash{}%
A \Index{namespace} is a mapping of names denoting declarations to actual declarations.
Let $NS$ be a namespace.
We say that a name $n$ \Index{is in} $NS$ if $n$ is a key of $NS$.
We say a declaration $d$ \NoIndex{is in} $NS$ if a key of $NS$ maps to $d$.
\LMHash{}%
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 getter with the same name in Dart.
Similarly one cannot declare a top-level function with the same name as a library variable or a class.
}
\LMHash{}%
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-.
}
\LMHash{}%
Dart is lexically scoped.
Scopes may nest.
A name or declaration $d$ is \Index{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 \Index{in scope} if $d$ is available in the current scope.
\LMHash{}%
If a declaration $d$ named $n$ is in the namespace induced by a scope $S$, then $d$ \Index{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}
\LMHash{}%
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 could create unexpected situations as code evolves.
Specifically, the behavior of code in a subclass could silently change 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 (discreetly).
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}
\LMLabel{privacy}
\LMHash{}%
Dart supports two levels of \Index{privacy}: public and private.
A declaration is \IndexCustom{private}{private!declaration}
if{}f its name is private,
otherwise it is \IndexCustom{public}{public!declaration}.
A name $q$ is \IndexCustom{private}{private!name}
if{}f any one of the identifiers that comprise $q$ is private,
otherwise it is \IndexCustom{public}{public!name}.
An identifier is \IndexCustom{private}{private!identifier}
if{}f it begins with an underscore (the \_ character)
otherwise it is \IndexCustom{public}{public!identifier}.
\LMHash{}%
A declaration $m$ is \Index{accessible to a 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.
}
\LMHash{}%
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 effect on the accessibility of the library or its members.
}
\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}
\LMLabel{concurrency}
\LMHash{}%
Dart code is always single threaded.
There is no shared-state concurrency in Dart.
Concurrency is supported via actor-like entities called \Index{isolates}.
\LMHash{}%
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}
\LMLabel{errorsAndWarnings}
\LMHash{}%
This specification distinguishes between several kinds of errors.
\LMHash{}%
\IndexCustom{Compile-time errors}{compile-time error}
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.
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.
A Dart development environment might choose to support error eliminating program transformations, e.g.,
replacing an erroneous expression by the invocation of a debugger.
It is outside the scope of this document to specify how such transformations work, and where they may be applied.
}
\LMHash{}%
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 \Index{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.
}
\LMHash{}%
\IndexCustom{Static warnings}{static warning}
are situations that do not preclude execution,
but which are unlikely to be intended,
and likely to cause bugs or inconveniences.
A static warning must be reported by a Dart compiler before the associated code is executed.
\LMHash{}%
When this specification says that a \Index{dynamic error} occurs,
it means that a corresponding error object is thrown.
When it says that a \Index{dynamic type error} occurs,
it represents a failed type check at run time,
and the object which is thrown implements \code{TypeError}.
\LMHash{}%
Whenever we say that an exception $ex$ is
\IndexCustom{thrown}{throwing an exception},
it acts like an expression had thrown (\ref{statementCompletion})
with $ex$ as exception object and with a stack trace
corresponding to the current system state.
When we say that a $C$ \IndexCustom{is thrown}{throwing a class},
where $C$ is a class, we mean that an instance of class $C$ is thrown.
\LMHash{}%
If an uncaught exception is thrown by a running isolate $A$, $A$ is immediately suspended.
\section{Variables}
\LMLabel{variables}
\LMHash{}%
Variables are storage locations in memory.
\begin{grammar}
<variableDeclaration> ::= <declaredIdentifier> (`,' <identifier>)*
<declaredIdentifier> ::= <metadata> \COVARIANT{}? <finalConstVarOrType> <identifier>
<finalConstVarOrType> ::= \LATE{}? \FINAL{} <type>?
\alt \CONST{} <type>?
\alt \LATE{}? <varOrType>
<varOrType> ::= \VAR{}
\alt <type>
<initializedVariableDeclaration> ::= \gnewline{}
<declaredIdentifier> (`=' <expression>)? (`,' <initializedIdentifier>)*
<initializedIdentifier> ::= <identifier> (`=' <expression>)?
<initializedIdentifierList> ::= <initializedIdentifier> (`,' <initializedIdentifier>)*
\end{grammar}
\LMHash{}%
A \synt{variableDeclaration} that declares two or more variables
is equivalent to multiple variable declarations declaring
the same set of variable names in the same order,
with the same type and modifiers.
\LMHash{}%
An \synt{initializedVariableDeclaration}
that declares two or more variables
is equivalent to multiple variable declarations declaring
the same set of variable names, in the same order,
with the same initialization, type, and modifiers.
\commentary{
For example,
\code{\VAR{} x, y;}
is equivalent to
\code{\VAR{} x; \VAR{} y;}
and
\code{\STATIC{} \FINAL{} String s1, s2 = "foo";}
is equivalent to
\code{\STATIC{} \FINAL{} String s1; \STATIC{} \FINAL{} String s2 = "foo";}.
}
\LMHash{}%
It is possible for a variable declaration to include the modifier \COVARIANT{}.
The effect of doing this with an instance variable is described elsewhere
(\ref{instanceVariables}).
It is a compile-time error for the declaration of
a variable which is not an instance variable
to include the modifier \COVARIANT{}.
\LMHash{}%
In a variable declaration of one of the forms
\code{$N$ $v$;}
\code{$N$ $v$ = $e$;}
where $N$ is derived from
\syntax{<metadata> <finalConstVarOrType>},
we say that $v$ is the \Index{declaring occurrence} of the identifier.
For every identifier which is not a declaring occurrence,
we say that it is an \Index{referencing occurrence}.
We also abbreviate that to say that an identifier is
a \Index{declaring identifier} respectively an \Index{referencing identifier}.
\commentary{
In an expression of the form \code{$e$.\id} it is possible that
$e$ has static type \DYNAMIC{} and \id{} cannot be associated with
any specific declaration named \id{} at compile-time,
but in this situation \id{} is still a referencing identifier.
}
\LMHash{}%
An \Index{initializing variable declaration}
is a variable declaration whose declaring identifier is
immediately followed by `\code{=}' and an \Index{initializing expression}.
\LMHash{}%
A variable declared at the top-level of a library is referred to as either a
\IndexCustom{library variable}{variable!library} or a
\IndexCustom{top-level variable}{variable!top-level}.
\LMHash{}%
A \IndexCustom{static variable}{variable!static}
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{}.
\LMHash{}%
A \IndexCustom{constant variable}{variable!constant}
is a variable whose declaration includes the modifier \CONST{}.
A constant variable must be initialized to a constant expression (\ref{constants}) or a compile-time error occurs.
\commentary{%
An initializing expression of a constant variable occurs in a constant context
(\ref{constantContexts}),
which means that \CONST{} modifiers need not be specified explicitly.%
}
\LMHash{}%
A \IndexCustom{final variable}{variable!final}
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.
A variable is final if{}f its declaration includes the modifier \FINAL{} or the modifier \CONST{}.