Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// 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
/// Pattern assignment
/// 1. Evaluate the right-hand side expression to a value v.
/// 2. Match v against the pattern on the left. When matching a variable pattern
/// against a value o, record that o will be the new value for the
/// corresponding variable, but do not store the variable.
/// 3. Once all destructuring and matching is done, store all of the assigned
/// variables with their corresponding values.
///
/// @description Check that if matching fails no any temporary values assigned
/// @author [email protected]

// SharedOptions=--enable-experiment=patterns,records

import "../../Utils/expect.dart";
import "patterns_lib.dart";

main() {
var v1 = 42;
Expect.throws(() {
(v1) = (3.14) as dynamic;
});
Expect.equals(42, v1);

int l1 = 42;
int l2 = 42;
Expect.throws(() {
dynamic pi = 3.14;
[l1, l2] = [0, pi];
});
Expect.equals(42, l1);
Expect.equals(42, l2);

int m1 = 42;
int m2 = 42;
Expect.throws(() {
dynamic pi = 3.14;
{"k1": m1, "k2": m2} = {"k1": 0, "k2": pi};
});
Expect.equals(42, m1);
Expect.equals(42, m2);

int r1 = 42;
int r2 = 42;
Expect.throws(() {
dynamic pi = 3.14;
(r1, r2) = (0, pi);
});
Expect.equals(42, r1);
Expect.equals(42, r2);

int o1 = 42;
int o2 = 42;
Expect.throws(() {
Circle(sizeAsInt: o1, areaAsDynamic: o2) = Circle(1);
});
Expect.equals(42, o1);
Expect.equals(42, o2);
}
68 changes: 68 additions & 0 deletions LanguageFeatures/Patterns/execution_switch_statement_A01_t01.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// 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
/// Switch statement
/// 1. Evaluate the switch value producing v.
/// 2. For each case:
/// i. Match the case's pattern against v. If the match fails then continue to
/// the next case (or default clause or exit the switch if there are no
/// other cases).
/// ii. If there is a guard clause, evaluate it. If it does not evaluate to a
/// Boolean, throw a runtime error. This can happen if the guard
/// expression's type is dynamic. If it evaluates to false, continue to the
/// next case (or default or exit).
/// iii. Find the nearest non-empty case body at or following this case.
/// You're allowed to have multiple empty cases where all preceding ones
/// share the same body with the last case.
/// iv. If the enclosing scope for the body is a shared case scope, then
/// initialize all shared variables the values of the corresponding
/// variables from the case scope. There will be no shared case scope and
/// nothing to copy if the body is only used by a single case.
/// v. Execute the body statement.
/// vi. If execution of the body statement continues with a label, and that
/// label is labeling a switch case of this switch, go to step 3 and
/// continue from that label.
/// vii. Otherwise the switch statement completes normally. An explicit break
/// is no longer required.
/// 3. If no case pattern matched and there is a default clause, execute the
/// statements after it.
/// 4. If the static type of v is an always-exhaustive type, no case matches,
/// and there is no default clause, then throw a runtime error.
///
/// @description Check that if matching fails then execution continues to the
/// next case or default (if any)
/// @author [email protected]

// SharedOptions=--enable-experiment=patterns

import "../../Utils/expect.dart";

main() {
String log = "";
var v = [42];
switch (v) {
case [String s]:
log += "case-1;";
case [bool b]:
log += "case-2;";
break;
case [1, 2]:
log += "case-3;";
}
Expect.equals("", log);

switch (v) {
case [_, 2]:
log += "case-1;";
case [bool _]:
log += "case-2;";
break;
case [1, _]:
log += "case-3;";
default:
log += "default";
}
Expect.equals("default", log);
}
63 changes: 63 additions & 0 deletions LanguageFeatures/Patterns/execution_switch_statement_A02_t01.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// 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
/// Switch statement
/// 1. Evaluate the switch value producing v.
/// 2. For each case:
/// i. Match the case's pattern against v. If the match fails then continue to
/// the next case (or default clause or exit the switch if there are no
/// other cases).
/// ii. If there is a guard clause, evaluate it. If it does not evaluate to a
/// Boolean, throw a runtime error. This can happen if the guard
/// expression's type is dynamic. If it evaluates to false, continue to the
/// next case (or default or exit).
/// iii. Find the nearest non-empty case body at or following this case.
/// You're allowed to have multiple empty cases where all preceding ones
/// share the same body with the last case.
/// iv. If the enclosing scope for the body is a shared case scope, then
/// initialize all shared variables the values of the corresponding
/// variables from the case scope. There will be no shared case scope and
/// nothing to copy if the body is only used by a single case.
/// v. Execute the body statement.
/// vi. If execution of the body statement continues with a label, and that
/// label is labeling a switch case of this switch, go to step 3 and
/// continue from that label.
/// vii. Otherwise the switch statement completes normally. An explicit break
/// is no longer required.
/// 3. If no case pattern matched and there is a default clause, execute the
/// statements after it.
/// 4. If the static type of v is an always-exhaustive type, no case matches,
/// and there is no default clause, then throw a runtime error.
///
/// @description Check that if there is a guard clause, it is evaluated if match
/// success
/// @author [email protected]

// SharedOptions=--enable-experiment=patterns

import "../../Utils/expect.dart";

String log = "";

bool guard(int v) {
log += "guard($v);";
return v == 42;
}

main() {
var v = [0, 42];
switch (v) {
case [int v1, var v2] when guard(v1):
log += "case-1;";
case [1, final v3] when guard(v3):
log += "case-2";
break;
case [0, var v4] when guard(v4):
log += "case-3;";
default:
log += "default";
}
Expect.equals("guard(0);guard(42);case-3;", log);
}
57 changes: 57 additions & 0 deletions LanguageFeatures/Patterns/execution_switch_statement_A02_t02.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// 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
/// Switch statement
/// 1. Evaluate the switch value producing v.
/// 2. For each case:
/// i. Match the case's pattern against v. If the match fails then continue to
/// the next case (or default clause or exit the switch if there are no
/// other cases).
/// ii. If there is a guard clause, evaluate it. If it does not evaluate to a
/// Boolean, throw a runtime error. This can happen if the guard
/// expression's type is dynamic. If it evaluates to false, continue to the
/// next case (or default or exit).
/// iii. Find the nearest non-empty case body at or following this case.
/// You're allowed to have multiple empty cases where all preceding ones
/// share the same body with the last case.
/// iv. If the enclosing scope for the body is a shared case scope, then
/// initialize all shared variables the values of the corresponding
/// variables from the case scope. There will be no shared case scope and
/// nothing to copy if the body is only used by a single case.
/// v. Execute the body statement.
/// vi. If execution of the body statement continues with a label, and that
/// label is labeling a switch case of this switch, go to step 3 and
/// continue from that label.
/// vii. Otherwise the switch statement completes normally. An explicit break
/// is no longer required.
/// 3. If no case pattern matched and there is a default clause, execute the
/// statements after it.
/// 4. If the static type of v is an always-exhaustive type, no case matches,
/// and there is no default clause, then throw a runtime error.
///
/// @description Check that it is a runtime error if guard value is not
/// assignable to bool
/// @author [email protected]

// SharedOptions=--enable-experiment=patterns

import "../../Utils/expect.dart";

dynamic guard(v) => v;

String test(v) {
switch(42) {
case 42 when guard(v):
return "Case body";
default:
return "default";
}
}

main() {
Expect.equals("Case body", test(true));
Expect.equals("default", test(false));
Expect.throws(() {test(42);});
}
81 changes: 81 additions & 0 deletions LanguageFeatures/Patterns/execution_switch_statement_A03_t01.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// 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
/// Switch statement
/// 1. Evaluate the switch value producing v.
/// 2. For each case:
/// i. Match the case's pattern against v. If the match fails then continue to
/// the next case (or default clause or exit the switch if there are no
/// other cases).
/// ii. If there is a guard clause, evaluate it. If it does not evaluate to a
/// Boolean, throw a runtime error. This can happen if the guard
/// expression's type is dynamic. If it evaluates to false, continue to the
/// next case (or default or exit).
/// iii. Find the nearest non-empty case body at or following this case.
/// You're allowed to have multiple empty cases where all preceding ones
/// share the same body with the last case.
/// iv. If the enclosing scope for the body is a shared case scope, then
/// initialize all shared variables the values of the corresponding
/// variables from the case scope. There will be no shared case scope and
/// nothing to copy if the body is only used by a single case.
/// v. Execute the body statement.
/// vi. If execution of the body statement continues with a label, and that
/// label is labeling a switch case of this switch, go to step 3 and
/// continue from that label.
/// vii. Otherwise the switch statement completes normally. An explicit break
/// is no longer required.
/// 3. If no case pattern matched and there is a default clause, execute the
/// statements after it.
/// 4. If the static type of v is an always-exhaustive type, no case matches,
/// and there is no default clause, then throw a runtime error.
///
/// @description Check that body of the matched case is executed
/// @author [email protected]

// SharedOptions=--enable-experiment=patterns

import "../../Utils/expect.dart";

String log = "";

bool guard(int n, bool b) {
log += "guard$n($b);";
return b;
}

void test(List<int> list) {
log = "";
switch (list) {
case [1, var v1] when guard(1, v1 == 1):
case [2, final v2] when guard(2, v2 == 2):
case [3, var v3] when guard(3, v3 == 3):
log += "shared body;";
case [4, var v4] when guard(4, v4 == 4):
log += "not shared body;";
default:
log += "default;";
}
}

main() {
test([1, 1]);
Expect.equals("guard1(true);shared body;", log);
test([2, 2]);
Expect.equals("guard2(true);shared body;", log);
test([3, 3]);
Expect.equals("guard3(true);shared body;", log);
test([4, 4]);
Expect.equals("guard4(true);not shared body;", log);
test([1, 42]);
Expect.equals("guard1(false);default;", log);
test([2, 42]);
Expect.equals("guard2(false);default;", log);
test([3, 42]);
Expect.equals("guard3(false);default;", log);
test([4, 42]);
Expect.equals("guard4(false);default;", log);
test([]);
Expect.equals("default;", log);
}
Loading