Skip to content

Commit

Permalink
#1401. [Patterns] Logical-or tests added (#1520)
Browse files Browse the repository at this point in the history
Authored by @sgrekhov.

Add logical-or tests. Using a log to detect execution of getters during a matching step.
  • Loading branch information
sgrekhov authored Nov 3, 2022
1 parent 0b4b314 commit 36cc25d
Show file tree
Hide file tree
Showing 8 changed files with 447 additions and 0 deletions.
48 changes: 48 additions & 0 deletions LanguageFeatures/Patterns/logical_or_A01_t01.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright (c) 2022, 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 logicalOrPattern ::= ( logicalOrPattern '|' )? logicalAndPattern
///
/// A pair of patterns separated by | matches if either of the branches match
///
/// A logical-or pattern may match even if one of its branches does not. That
/// means that any variables in the non-matching branch would not be
/// initialized. To avoid problems stemming from that, the following
/// restrictions apply:
///
/// The two branches must define the same set of variables.
///
/// If the left branch matches, the right branch is not evaluated. This
/// determines which value the variable gets if both branches would have
/// matched. In that case, it will always be the value from the left branch.
///
/// @description Checks logical-or pattern in a switch expression
/// @author [email protected]
// SharedOptions=--enable-experiment=patterns

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

enum Color {
white,
red,
yellow,
blue,
black;
}

bool isPrimary(Color color) {
return switch (color) {
case Color.red | Color.yellow | Color.blue => true;
default => false;
};
}

main() {
Expect.isFalse(isPrimary(Color.black));
Expect.isFalse(isPrimary(Color.white));
Expect.isTrue(isPrimary(Color.red));
Expect.isTrue(isPrimary(Color.yellow));
Expect.isTrue(isPrimary(Color.blue));
}
40 changes: 40 additions & 0 deletions LanguageFeatures/Patterns/logical_or_A01_t02.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Copyright (c) 2022, 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 logicalOrPattern ::= ( logicalOrPattern '|' )? logicalAndPattern
///
/// A pair of patterns separated by | matches if either of the branches match
///
/// A logical-or pattern may match even if one of its branches does not. That
/// means that any variables in the non-matching branch would not be
/// initialized. To avoid problems stemming from that, the following
/// restrictions apply:
///
/// The two branches must define the same set of variables.
///
/// If the left branch matches, the right branch is not evaluated. This
/// determines which value the variable gets if both branches would have
/// matched. In that case, it will always be the value from the left branch.
///
/// @description Checks logical-or subpattern in a switch expression
/// @author [email protected]
// SharedOptions=--enable-experiment=patterns

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

bool matches(List list) => switch (list) {
case [1 | 2, 3] => true;
default => false;
};

main() {
Expect.isFalse(matches([0, 3]));
Expect.isFalse(matches([2, 2]));
Expect.isFalse(matches([2, 3, 4]));
Expect.isFalse(matches([2, "3"]));
Expect.isFalse(matches(["1", 3]));
Expect.isTrue(matches([1, 3]));
Expect.isTrue(matches([2, 3]));
}
46 changes: 46 additions & 0 deletions LanguageFeatures/Patterns/logical_or_A02_t01.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright (c) 2022, 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 logicalOrPattern ::= ( logicalOrPattern '|' )? logicalAndPattern
///
/// A pair of patterns separated by | matches if either of the branches match
///
/// A logical-or pattern may match even if one of its branches does not. That
/// means that any variables in the non-matching branch would not be
/// initialized. To avoid problems stemming from that, the following
/// restrictions apply:
///
/// The two branches must define the same set of variables.
///
/// If the left branch matches, the right branch is not evaluated. This
/// determines which value the variable gets if both branches would have
/// matched. In that case, it will always be the value from the left branch.
///
/// @description Checks logical-or pattern in a switch statement
/// @author [email protected]
// SharedOptions=--enable-experiment=patterns

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

void test(Shape shape, double expectedArea, Type expectedType, bool match) {
switch (shape) {
case Square(area: var s) | Circle(area: var s):
Expect.equals(s, expectedArea);
Expect.equals(expectedType, shape.runtimeType);
Expect.isTrue(match);
break;
default:
Expect.equals(s, expectedArea);
Expect.equals(expectedType, shape.runtimeType);
Expect.isFalse(match);
}
}

main() {
test(Circle(1), 3.14, Circle, true);
test(Square(2), 4, Square, true);
test(Rectangle(2, 1), 2, Rectangle, false);
}
45 changes: 45 additions & 0 deletions LanguageFeatures/Patterns/logical_or_A02_t02.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (c) 2022, 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 logicalOrPattern ::= ( logicalOrPattern '|' )? logicalAndPattern
///
/// A pair of patterns separated by | matches if either of the branches match
///
/// A logical-or pattern may match even if one of its branches does not. That
/// means that any variables in the non-matching branch would not be
/// initialized. To avoid problems stemming from that, the following
/// restrictions apply:
///
/// The two branches must define the same set of variables.
///
/// If the left branch matches, the right branch is not evaluated. This
/// determines which value the variable gets if both branches would have
/// matched. In that case, it will always be the value from the left branch.
///
/// @description Checks logical-or subpattern in a switch statement
/// @author [email protected]
// SharedOptions=--enable-experiment=patterns

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

bool matches(List list) {
bool result = false;
switch (list) {
case [1 | 2, 3]:
result = true;
default:
};
return result;
}

main() {
Expect.isFalse(matches([0, 3]));
Expect.isFalse(matches([2, 2]));
Expect.isFalse(matches([2, 3, 4]));
Expect.isFalse(matches([2, "3"]));
Expect.isFalse(matches(["1", 3]));
Expect.isTrue(matches([1, 3]));
Expect.isTrue(matches([2, 3]));
}
46 changes: 46 additions & 0 deletions LanguageFeatures/Patterns/logical_or_A03_t01.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright (c) 2022, 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 logicalOrPattern ::= ( logicalOrPattern '|' )? logicalAndPattern
///
/// A pair of patterns separated by | matches if either of the branches match
///
/// A logical-or pattern may match even if one of its branches does not. That
/// means that any variables in the non-matching branch would not be
/// initialized. To avoid problems stemming from that, the following
/// restrictions apply:
///
/// The two branches must define the same set of variables.
///
/// If the left branch matches, the right branch is not evaluated. This
/// determines which value the variable gets if both branches would have
/// matched. In that case, it will always be the value from the left branch.
///
/// @description Checks that it is a compile-time error if two branches of
/// logical-or pattern define different sets of variables
/// @author [email protected]
// SharedOptions=--enable-experiment=patterns

import "patterns_lib.dart";

main() {
Shape shape = Circle(1);
switch (shape) {
case Square(area: var s1) | Circle(area: var s2):
// ^^
// [analyzer] unspecified
// [cfe] unspecified
print("Square or Circle");
break;
case Rectangle(x: var x, y: var width) | Rectangle(:var x, :var y):
// ^
// [analyzer] unspecified
// [cfe] unspecified
print("Rectangle");
break;
default:
print("Other");
}
}
56 changes: 56 additions & 0 deletions LanguageFeatures/Patterns/logical_or_A04_t01.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// Copyright (c) 2022, 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 logicalOrPattern ::= ( logicalOrPattern '|' )? logicalAndPattern
///
/// A pair of patterns separated by | matches if either of the branches match
///
/// A logical-or pattern may match even if one of its branches does not. That
/// means that any variables in the non-matching branch would not be
/// initialized. To avoid problems stemming from that, the following
/// restrictions apply:
///
/// The two branches must define the same set of variables.
///
/// If the left branch matches, the right branch is not evaluated. This
/// determines which value the variable gets if both branches would have
/// matched. In that case, it will always be the value from the left branch.
///
/// @description Checks that if the left branch matches, the right branch is not
/// evaluated
/// @author [email protected]
// SharedOptions=--enable-experiment=patterns

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

main() {
Shape shape1 = Square(1);
switch (shape1) {
case Square(area: var s) | Shape(area: var s):
Expect.equals("Square.area", shape1.log);
break;
default:
print("Other");
}

Shape shape2 = Square(2);
switch (shape2) {
case Square(area: 2) | Square(area: 4) | Square(area: 4):
Expect.equals("Circle.area=2;Circle.area=4;", shape2.log);
break;
default:
print("Other");
}

Shape shape3 = Shape();
switch (shape3) {
case Circle(area: 0) | Square(area: 1) | Shape(area: 0):
Expect.equals("Shape.area=0;", shape3.log);
break;
default:
print("Other");
}
}
72 changes: 72 additions & 0 deletions LanguageFeatures/Patterns/logical_or_A04_t02.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// Copyright (c) 2022, 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 logicalOrPattern ::= ( logicalOrPattern '|' )? logicalAndPattern
///
/// A pair of patterns separated by | matches if either of the branches match
///
/// A logical-or pattern may match even if one of its branches does not. That
/// means that any variables in the non-matching branch would not be
/// initialized. To avoid problems stemming from that, the following
/// restrictions apply:
///
/// The two branches must define the same set of variables.
///
/// If the left branch matches, the right branch is not evaluated. This
/// determines which value the variable gets if both branches would have
/// matched. In that case, it will always be the value from the left branch.
///
/// @description Checks that if the left branch doesn't match, then the right
/// branch is evaluated
/// @author [email protected]
// SharedOptions=--enable-experiment=patterns

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

main() {
Shape shape1 = Square(1);
switch (shape1) {
case Square(area: 2) | Square(area: 1):
Expect.equals("Square.area=2;Square.area=1;", shape1.log);
break;
default:
print("Other");
}

Shape shape2 = Shape();
switch (shape2) {
case Square(area: 2) | Rectangle(area: 1) | Shape(area: 0):
Expect.equals("Shape.area=0;", shape2.log);
break;
default:
print("Other");
}

Shape shape3 = Circle(1);
switch (shape2) {
case Circle(area: 2) | Circle(area: 1) | Circle(area: 0)
| Circle(area: 3.14):
Expect.equals(
"Circle.area=2;Circle.area=1;Circle.area=0;Circle.area=3.14;",
shape3.log);
break;
default:
print("Other");
}

Shape shape4 = Rectangle(1, 2);
bool other = false;
switch (shape4) {
case Rectangle(area: 3) | Rectangle(area: 1) | Rectangle(area: 42):
Expect.fail("No branches should match");
break;
default:
other = true;
Expect.equals("Rectangle.area=3;Rectangle.area=1;Rectangle.area=42;",
shape4.log);
}
Expect.isTrue(other);
}
Loading

0 comments on commit 36cc25d

Please sign in to comment.