blob: 91919ba4144f0611fe29d60d89bd68cad39664a0 [file]
// Copyright (c) 2023, 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
/// A statement of the form:
///
/// for (<keyword> <pattern> in <expression>) <statement>
///
/// Where <keyword> is var or final is treated like so:
/// 1. Let I be the static type of <expression>, inferred using context type
/// schema Iterable<P> where P is the context type schema of <pattern>.
/// 2. Calculate the element type of I:
/// i. If I implements Iterable<T> for some T then E is T.
/// ii. Else if I is dynamic then E is dynamic.
/// iii. Else it is a compile-time error.
/// 3. Type check <pattern> with matched value type E.
/// 4. If there are no compile-time errors, then execution proceeds as the
/// following code, where id1 and id2 are fresh identifiers:
/// ```dart
/// var id1 = <expression>;
/// var id2 = id1.iterator;
/// while (id2.moveNext()) {
/// <keyword> <pattern> = id2.current;
/// { <statement> }
/// }
/// ```
/// @description Checks that if `I` implements `Iterable<T>` for some `T` then
/// `E` is `T`. Test `T` inferred from `<pattern>` to `<expression>` and from
/// `<expression>` to `<pattern>`
/// @author sgrekhov22@gmail.com
import "../../Utils/expect.dart";
import "../../Utils/static_type_helper.dart";
import "patterns_lib.dart";
extension Storing on Object? {
static dynamic stored;
void get store => stored = this;
}
main() {
String log = "";
for (var (num v1) in [1, 2, 3]..store) {
v1.expectStaticType<Exactly<num>>();
log += "$v1;";
}
Expect.equals("1;2;3;", log);
Expect.isTrue(Storing.stored is List<num>);
Storing.stored.add(42);
Storing.stored.add(3.14);
log = "";
for (final (v2) in <num>[1, 2, 3]) {
v2.expectStaticType<Exactly<num>>();
log += "$v2;";
}
Expect.equals("1;2;3;", log);
log = "";
log = "";
for (var <num>[v3] in [[1], [2], [3]]..store) {
v3.expectStaticType<Exactly<num>>();
log += "$v3;";
}
Expect.equals("1;2;3;", log);
Expect.isTrue(Storing.stored is List<List<num>>);
Storing.stored.first.add(42);
Storing.stored.first.add(3.14);
log = "";
for (final [v4] in <List<num>>[[1], [2], [3]]) {
v4.expectStaticType<Exactly<num>>();
log += "$v4;";
}
Expect.equals("1;2;3;", log);
log = "";
for (var <String, num>{"k1": v5} in [{"k1": 1}]..store) {
v5.expectStaticType<Exactly<num>>();
log += "$v5;";
}
Expect.equals("1;", log);
Expect.isTrue(Storing.stored is List<Map<String, num>>);
Expect.isTrue(Storing.stored.first is Map<String, num>);
Storing.stored.first["answer"] = 42;
Storing.stored.first["pi"] = 3.14;
log = "";
for (final {"k1": v6} in <Map<String, num>>[{"k1": 1}]) {
v6.expectStaticType<Exactly<num>>();
log += "$v6;";
}
Expect.equals("1;", log);
log = "";
for (var (num v7, n: num v8) in [(1, n: 2)]..store) {
v7.expectStaticType<Exactly<num>>();
v8.expectStaticType<Exactly<num>>();
log += "$v7;$v8;";
}
Expect.equals("1;2;", log);
Expect.isTrue(Storing.stored is List<(num, {num n})>);
log = "";
for (final (v9, n: v10) in <(num, {num n})>[(1, n: 2)]) {
v9.expectStaticType<Exactly<num>>();
v10.expectStaticType<Exactly<num>>();
log += "$v9;$v10;";
}
Expect.equals("1;2;", log);
log = "";
for (var Square<Centimeter>(area: v11) in [Square(1)]..store) {
v11.expectStaticType<Exactly<Unit<Centimeter>>>();
log += "$v11;";
}
Expect.equals("1;", log);
Expect.isTrue(Storing.stored is List<Square<Centimeter>>);
log = "";
for (final Square(area: v12) in <Square<Centimeter>>[Square<Centimeter>(1)]) {
v12.expectStaticType<Exactly<Unit<Centimeter>>>();
log += "$v12;";
}
Expect.equals("1;", log);
log = "";
for (var (num v1 && v2) in [1, 2, 3]..store) {
v1.expectStaticType<Exactly<num>>();
v2.expectStaticType<Exactly<num>>();
log += "$v1&&$v2;";
}
Expect.equals("1&&1;2&&2;3&&3;", log);
Expect.isTrue(Storing.stored is List<num>);
Storing.stored.add(42);
Storing.stored.add(3.14);
}