diff --git a/LanguageFeatures/Static-access-shorthand/grammar_A01_t03.dart b/LanguageFeatures/Static-access-shorthand/grammar_A01_t03.dart index 19ac762638..c0dcfc954d 100644 --- a/LanguageFeatures/Static-access-shorthand/grammar_A01_t03.dart +++ b/LanguageFeatures/Static-access-shorthand/grammar_A01_t03.dart @@ -43,6 +43,6 @@ main() { E e2 = .staticMethod(); Expect.equals("v2", e2.value); - E e3 = E.values[1]; + E e3 = .values[1]; Expect.equals(E.v2, e3); } diff --git a/LanguageFeatures/Static-access-shorthand/grammar_A03_t01.dart b/LanguageFeatures/Static-access-shorthand/grammar_A03_t01.dart new file mode 100644 index 0000000000..a4ea4a4858 --- /dev/null +++ b/LanguageFeatures/Static-access-shorthand/grammar_A03_t01.dart @@ -0,0 +1,29 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// @assertion We also add `.` to the tokens that an expression statement cannot +/// start with. +/// +/// @description Checks that numerical literal like `.123` is still not an error +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=enum-shorthands + +main() { + .123; + + (.123); + + var v1 = .123 + 1; + + if (.123 > 0) {} + + const half = .5; + + final zero = 0 - .0; + + .314e+1; + + var pi = .214e+1 + 1; +} diff --git a/LanguageFeatures/Static-access-shorthand/semantics_A01_t01.dart b/LanguageFeatures/Static-access-shorthand/semantics_A01_t01.dart new file mode 100644 index 0000000000..0bae665242 --- /dev/null +++ b/LanguageFeatures/Static-access-shorthand/semantics_A01_t01.dart @@ -0,0 +1,97 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// @assertion Dart semantics, static and dynamic, do not follow the grammar +/// precisely. For example, a static member invocation expression of the form +/// `C.id(e2)` is treated as an atomic entity for type inference (and +/// runtime semantics). It’s not a combination of doing a `C.id` tear-off, then +/// a `` instantiation and then an `(e2)` invocation. The context type of +/// that entire expression is used throughout the inference, where +/// `(e1.id)(e2)` has `(e1.id)` in a position where it has no context +/// type. +/// +/// Because of that, the specification of the static and runtime semantics of +/// the new constructs needs to address all the forms `.id`, `.id`, +/// `.id(args)`, `.id(args)`, `.new` or `.new(args)`. +/// ... +/// The general rule is that any of the expression forms above, starting with +/// `.id`, are treated exactly as if they were prefixed by a fresh identifier +/// `X` which denotes an accessible type alias for the greatest closure of the +/// context type scheme of the following primary and selector chain. +/// +/// @description Checks that the processing of the context type for shorthand +/// of the forms `.id`, `.id(args)` and `.id(args)` includes a type +/// alias expansion. +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=enum-shorthands + +import '../../Utils/expect.dart'; + +class C { + T t; + C(this.t); + + static C get id1 => C(1); + static C id2(X x) => C(x); +} + +typedef CAlias = C; +typedef CInt = C; + +mixin M on C { + static M get id1 => MC(1); + static M id2(X x) => MC(x); +} + +class MC = C with M; + +typedef MAlias = M; +typedef MInt = M; + +enum E { + e1(1), e2("2"); + final T t; + const E(this.t); + + static E get id1 => E.e1; + static E id2() => E.e2; +} + +typedef EAlias = E; +typedef EInt = E; + +extension type ET(T t) { + static ET get id1 => ET(1); + static ET id2(X x) => ET(x); +} + +typedef ETAlias = ET; +typedef ETInt = ET; + +main() { + CAlias c1 = .id1; + Expect.equals(1, c1.t); + + CInt c2 = .id2(2); + Expect.equals(2, c2.t); + + MAlias m1 = .id1; + Expect.equals(1, m1.t); + + MInt m2 = .id2(2); + Expect.equals(2, m2.t); + + EInt e1 = .id1; + Expect.equals(1, e1.t); + + EAlias e2 = .id2(); + Expect.equals("2", e2.t); + + ETAlias et1 = .id1; + Expect.equals(1, et1.t); + + ETInt et2 = .id2(2); + Expect.equals(2, et2.t); +} diff --git a/LanguageFeatures/Static-access-shorthand/semantics_A01_t02.dart b/LanguageFeatures/Static-access-shorthand/semantics_A01_t02.dart new file mode 100644 index 0000000000..a8dbf543c3 --- /dev/null +++ b/LanguageFeatures/Static-access-shorthand/semantics_A01_t02.dart @@ -0,0 +1,57 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// @assertion Dart semantics, static and dynamic, do not follow the grammar +/// precisely. For example, a static member invocation expression of the form +/// `C.id(e2)` is treated as an atomic entity for type inference (and +/// runtime semantics). It’s not a combination of doing a `C.id` tear-off, then +/// a `` instantiation and then an `(e2)` invocation. The context type of +/// that entire expression is used throughout the inference, where +/// `(e1.id)(e2)` has `(e1.id)` in a position where it has no context +/// type. +/// +/// Because of that, the specification of the static and runtime semantics of +/// the new constructs needs to address all the forms `.id`, `.id`, +/// `.id(args)`, `.id(args)`, `.new` or `.new(args)`. +/// ... +/// The general rule is that any of the expression forms above, starting with +/// `.id`, are treated exactly as if they were prefixed by a fresh identifier +/// `X` which denotes an accessible type alias for the greatest closure of the +/// context type scheme of the following primary and selector chain. +/// +/// @description Checks that the processing of the context type for shorthand +/// of the forms `.id`, `.id(args)` and `.id(args)` includes a type +/// alias expansion. Test unprefixed import. +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=enum-shorthands + +import '../../Utils/expect.dart'; +import 'shorthand_lib.dart'; + +main() { + CAlias c1 = .id1; + Expect.equals(1, c1.t); + + CInt c2 = .id2(2); + Expect.equals(2, c2.t); + + MAlias m1 = .id1; + Expect.equals(1, m1.t); + + MInt m2 = .id2(2); + Expect.equals(2, m2.t); + + EInt e1 = .id1; + Expect.equals(1, e1.t); + + EAlias e2 = .id2(); + Expect.equals("2", e2.t); + + ETAlias et1 = .id1; + Expect.equals(1, et1.t); + + ETInt et2 = .id2(2); + Expect.equals(2, et2.t); +} diff --git a/LanguageFeatures/Static-access-shorthand/semantics_A01_t03.dart b/LanguageFeatures/Static-access-shorthand/semantics_A01_t03.dart new file mode 100644 index 0000000000..60eaa9b542 --- /dev/null +++ b/LanguageFeatures/Static-access-shorthand/semantics_A01_t03.dart @@ -0,0 +1,57 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// @assertion Dart semantics, static and dynamic, do not follow the grammar +/// precisely. For example, a static member invocation expression of the form +/// `C.id(e2)` is treated as an atomic entity for type inference (and +/// runtime semantics). It’s not a combination of doing a `C.id` tear-off, then +/// a `` instantiation and then an `(e2)` invocation. The context type of +/// that entire expression is used throughout the inference, where +/// `(e1.id)(e2)` has `(e1.id)` in a position where it has no context +/// type. +/// +/// Because of that, the specification of the static and runtime semantics of +/// the new constructs needs to address all the forms `.id`, `.id`, +/// `.id(args)`, `.id(args)`, `.new` or `.new(args)`. +/// ... +/// The general rule is that any of the expression forms above, starting with +/// `.id`, are treated exactly as if they were prefixed by a fresh identifier +/// `X` which denotes an accessible type alias for the greatest closure of the +/// context type scheme of the following primary and selector chain. +/// +/// @description Checks that the processing of the context type for shorthand +/// of the forms `.id`, `.id(args)` and `.id(args)` includes a type +/// alias expansion. Test prefixed import. +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=enum-shorthands + +import '../../Utils/expect.dart'; +import 'shorthand_lib.dart' as p; + +main() { + p.CAlias c1 = .id1; + Expect.equals(1, c1.t); + + p.CInt c2 = .id2(2); + Expect.equals(2, c2.t); + + p.MAlias m1 = .id1; + Expect.equals(1, m1.t); + + p.MInt m2 = .id2(2); + Expect.equals(2, m2.t); + + p.EInt e1 = .id1; + Expect.equals(1, e1.t); + + p.EAlias e2 = .id2(); + Expect.equals("2", e2.t); + + p.ETAlias et1 = .id1; + Expect.equals(1, et1.t); + + p.ETInt et2 = .id2(2); + Expect.equals(2, et2.t); +} diff --git a/LanguageFeatures/Static-access-shorthand/semantics_A01_t04.dart b/LanguageFeatures/Static-access-shorthand/semantics_A01_t04.dart new file mode 100644 index 0000000000..58a0209655 --- /dev/null +++ b/LanguageFeatures/Static-access-shorthand/semantics_A01_t04.dart @@ -0,0 +1,113 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// @assertion Dart semantics, static and dynamic, do not follow the grammar +/// precisely. For example, a static member invocation expression of the form +/// `C.id(e2)` is treated as an atomic entity for type inference (and +/// runtime semantics). It’s not a combination of doing a `C.id` tear-off, then +/// a `` instantiation and then an `(e2)` invocation. The context type of +/// that entire expression is used throughout the inference, where +/// `(e1.id)(e2)` has `(e1.id)` in a position where it has no context +/// type. +/// +/// Because of that, the specification of the static and runtime semantics of +/// the new constructs needs to address all the forms `.id`, `.id`, +/// `.id(args)`, `.id(args)`, `.new` or `.new(args)`. +/// ... +/// The general rule is that any of the expression forms above, starting with +/// `.id`, are treated exactly as if they were prefixed by a fresh identifier +/// `X` which denotes an accessible type alias for the greatest closure of the +/// context type scheme of the following primary and selector chain. +/// +/// @description Checks that the processing of the context type for shorthand +/// of the form `.id` includes a type alias expansion. +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=enum-shorthands + +import '../../Utils/expect.dart'; + +class C { + static X id(X x) => x; +} +typedef CAlias = C; + +mixin M { + static X id(X x) => x; +} +typedef MAlias = M; +class MA = Object with M; + +enum E { + e0; + static X id(X x) => x; +} +typedef EAlias = E; + +extension type ET(int _) implements Object { + static X id(X x) => x; +} +typedef ETAlias = ET; + +main() { + Object o = C(); + if (o is C) { + o = .id; + if (o is Function) { + Expect.equals(42, o(42)); + } + } + o = C(); + if (o is CAlias) { + o = .id; + if (o is Function) { + Expect.equals(42, o(42)); + } + } + + o = MA(); + if (o is M) { + o = .id; + if (o is Function) { + Expect.equals(42, o(42)); + } + } + o = MA(); + if (o is MAlias) { + o = .id; + if (o is Function) { + Expect.equals(42, o(42)); + } + } + + o = E.e0; + if (o is E) { + o = .id; + if (o is Function) { + Expect.equals(42, o(42)); + } + } + o = E.e0; + if (o is EAlias) { + o = .id; + if (o is Function) { + Expect.equals(42, o(42)); + } + } + + o = ET(0); + if (o is ET) { + o = .id; + if (o is Function) { + Expect.equals(42, o(42)); + } + } + o = ET(1); + if (o is EAlias) { + o = .id; + if (o is Function) { + Expect.equals(42, o(42)); + } + } +} diff --git a/LanguageFeatures/Static-access-shorthand/semantics_A01_t05.dart b/LanguageFeatures/Static-access-shorthand/semantics_A01_t05.dart new file mode 100644 index 0000000000..b8eb764880 --- /dev/null +++ b/LanguageFeatures/Static-access-shorthand/semantics_A01_t05.dart @@ -0,0 +1,93 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// @assertion Dart semantics, static and dynamic, do not follow the grammar +/// precisely. For example, a static member invocation expression of the form +/// `C.id(e2)` is treated as an atomic entity for type inference (and +/// runtime semantics). It’s not a combination of doing a `C.id` tear-off, then +/// a `` instantiation and then an `(e2)` invocation. The context type of +/// that entire expression is used throughout the inference, where +/// `(e1.id)(e2)` has `(e1.id)` in a position where it has no context +/// type. +/// +/// Because of that, the specification of the static and runtime semantics of +/// the new constructs needs to address all the forms `.id`, `.id`, +/// `.id(args)`, `.id(args)`, `.new` or `.new(args)`. +/// ... +/// The general rule is that any of the expression forms above, starting with +/// `.id`, are treated exactly as if they were prefixed by a fresh identifier +/// `X` which denotes an accessible type alias for the greatest closure of the +/// context type scheme of the following primary and selector chain. +/// +/// @description Checks that the processing of the context type for shorthand +/// of the form `.id` includes a type alias expansion. Test unprefixed +/// import. +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=enum-shorthands + +import '../../Utils/expect.dart'; +import 'shorthand_lib.dart'; + +main() { + Object o = C(); + if (o is C) { + o = .id3; + if (o is Function) { + Expect.equals(42, o(42)); + } + } + o = C(); + if (o is CAlias) { + o = .id3; + if (o is Function) { + Expect.equals(42, o(42)); + } + } + + o = MA(); + if (o is M) { + o = .id3; + if (o is Function) { + Expect.equals(42, o(42)); + } + } + o = MA(); + if (o is MAlias) { + o = .id3; + if (o is Function) { + Expect.equals(42, o(42)); + } + } + + o = E.e0; + if (o is E) { + o = .id3; + if (o is Function) { + Expect.equals(42, o(42)); + } + } + o = E.e0; + if (o is EAlias) { + o = .id3; + if (o is Function) { + Expect.equals(42, o(42)); + } + } + + o = ET(0); + if (o is ET) { + o = .id3; + if (o is Function) { + Expect.equals(42, o(42)); + } + } + o = ET(1); + if (o is EAlias) { + o = .id3; + if (o is Function) { + Expect.equals(42, o(42)); + } + } +} diff --git a/LanguageFeatures/Static-access-shorthand/semantics_A01_t06.dart b/LanguageFeatures/Static-access-shorthand/semantics_A01_t06.dart new file mode 100644 index 0000000000..ac5fa05f6d --- /dev/null +++ b/LanguageFeatures/Static-access-shorthand/semantics_A01_t06.dart @@ -0,0 +1,93 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// @assertion Dart semantics, static and dynamic, do not follow the grammar +/// precisely. For example, a static member invocation expression of the form +/// `C.id(e2)` is treated as an atomic entity for type inference (and +/// runtime semantics). It’s not a combination of doing a `C.id` tear-off, then +/// a `` instantiation and then an `(e2)` invocation. The context type of +/// that entire expression is used throughout the inference, where +/// `(e1.id)(e2)` has `(e1.id)` in a position where it has no context +/// type. +/// +/// Because of that, the specification of the static and runtime semantics of +/// the new constructs needs to address all the forms `.id`, `.id`, +/// `.id(args)`, `.id(args)`, `.new` or `.new(args)`. +/// ... +/// The general rule is that any of the expression forms above, starting with +/// `.id`, are treated exactly as if they were prefixed by a fresh identifier +/// `X` which denotes an accessible type alias for the greatest closure of the +/// context type scheme of the following primary and selector chain. +/// +/// @description Checks that the processing of the context type for shorthand +/// of the form `.id` includes a type alias expansion. Test prefixed +/// import. +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=enum-shorthands + +import '../../Utils/expect.dart'; +import 'shorthand_lib.dart' as p; + +main() { + Object o = p.C(); + if (o is p.C) { + o = .id3; + if (o is Function) { + Expect.equals(42, o(42)); + } + } + o = p.C(); + if (o is p.CAlias) { + o = .id3; + if (o is Function) { + Expect.equals(42, o(42)); + } + } + + o = p.MA(); + if (o is p.M) { + o = .id3; + if (o is Function) { + Expect.equals(42, o(42)); + } + } + o = p.MA(); + if (o is p.MAlias) { + o = .id3; + if (o is Function) { + Expect.equals(42, o(42)); + } + } + + o = p.E.e0; + if (o is p.E) { + o = .id3; + if (o is Function) { + Expect.equals(42, o(42)); + } + } + o = p.E.e0; + if (o is p.EAlias) { + o = .id3; + if (o is Function) { + Expect.equals(42, o(42)); + } + } + + o = p.ET(0); + if (o is p.ET) { + o = .id3; + if (o is Function) { + Expect.equals(42, o(42)); + } + } + o = p.ET(1); + if (o is p.EAlias) { + o = .id3; + if (o is Function) { + Expect.equals(42, o(42)); + } + } +} diff --git a/LanguageFeatures/Static-access-shorthand/shorthand_lib.dart b/LanguageFeatures/Static-access-shorthand/shorthand_lib.dart new file mode 100644 index 0000000000..86900ab2d9 --- /dev/null +++ b/LanguageFeatures/Static-access-shorthand/shorthand_lib.dart @@ -0,0 +1,54 @@ +// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +/// @assertion Common library for static access shorthand tests. +/// +/// @author sgrekhov22@gmail.com + +// SharedOptions=--enable-experiment=enum-shorthands + +class C { + T t; + C(this.t); + + static C get id1 => C(1); + static C id2(X x) => C(x); + static X id3(X x) => x; +} + +typedef CAlias = C; +typedef CInt = C; + +mixin M on C { + static M get id1 => MC(1); + static M id2(X x) => MC(x); + static X id3(X x) => x; +} + +class MC = C with M; + +typedef MAlias = M; +typedef MInt = M; + +enum E { + e1(1), e2("2"); + final T t; + const E(this.t); + + static E get id1 => E.e1; + static E id2() => E.e2; + static X id3(X x) => x; +} + +typedef EAlias = E; +typedef EInt = E; + +extension type ET(T t) { + static ET get id1 => ET(1); + static ET id2(X x) => ET(x); + static X id3(X x) => x; +} + +typedef ETAlias = ET; +typedef ETInt = ET;