-
Notifications
You must be signed in to change notification settings - Fork 28
#1401. Patterns execution. Assignment and switch statement tests #1857
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
63 changes: 63 additions & 0 deletions
63
LanguageFeatures/Patterns/execution_pattern_assignment_A01_t01.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
eernstg marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
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); | ||
eernstg marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
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); | ||
eernstg marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
}); | ||
Expect.equals(42, o1); | ||
Expect.equals(42, o2); | ||
} |
68 changes: 68 additions & 0 deletions
68
LanguageFeatures/Patterns/execution_switch_statement_A01_t01.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
63
LanguageFeatures/Patterns/execution_switch_statement_A02_t01.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
57
LanguageFeatures/Patterns/execution_switch_statement_A02_t02.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
81
LanguageFeatures/Patterns/execution_switch_statement_A03_t01.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.