Skip to content

Commit 777d706

Browse files
chloestefantsovaCommit Queue
authored and
Commit Queue
committed
[cfe] Implement the desugaring for RelationalPattern
Part of #49749 Change-Id: I8b1da2a3c3f25e5147a519cf3d05e3ac2e42f401 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/267341 Reviewed-by: Johnni Winther <[email protected]> Commit-Queue: Chloe Stefantsova <[email protected]>
1 parent a42ccdb commit 777d706

12 files changed

+252
-8
lines changed

pkg/front_end/lib/src/fasta/kernel/forest.dart

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,21 @@ class Forest {
831831
..fileOffset = fileOffset;
832832
}
833833

834+
EqualsCall createEqualsCall(int fileOffset, Expression left, Expression right,
835+
FunctionType functionType, Procedure interfaceTarget) {
836+
// ignore: unnecessary_null_comparison
837+
assert(fileOffset != null);
838+
return new EqualsCall(left, right,
839+
functionType: functionType, interfaceTarget: interfaceTarget)
840+
..fileOffset = fileOffset;
841+
}
842+
843+
EqualsNull createEqualsNull(int fileOffset, Expression expression) {
844+
// ignore: unnecessary_null_comparison
845+
assert(fileOffset != null);
846+
return new EqualsNull(expression)..fileOffset = fileOffset;
847+
}
848+
834849
BinaryExpression createBinary(
835850
int fileOffset, Expression left, Name binaryName, Expression right) {
836851
// ignore: unnecessary_null_comparison

pkg/front_end/lib/src/fasta/kernel/internal_ast.dart

Lines changed: 71 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import 'package:_fe_analyzer_shared/src/type_inference/type_analyzer.dart';
2626
import 'package:_fe_analyzer_shared/src/type_inference/type_analysis_result.dart';
2727

2828
import '../builder/type_alias_builder.dart';
29+
import '../fasta_codes.dart';
2930
import '../names.dart';
3031
import '../problems.dart' show unsupported;
3132
import '../type_inference/inference_visitor.dart';
@@ -5499,8 +5500,76 @@ class RelationalPattern extends Pattern {
54995500
@override
55005501
Expression? makeCondition(VariableDeclaration matchedExpressionVariable,
55015502
InferenceVisitorBase inferenceVisitor) {
5502-
return new InvalidExpression(
5503-
"Unimplemented RelationalMatcher.makeCondition");
5503+
DartType receiverType = matchedExpressionVariable.type;
5504+
Name name;
5505+
switch (kind) {
5506+
case RelationalPatternKind.equals:
5507+
case RelationalPatternKind.notEquals:
5508+
Expression result;
5509+
if (expression is NullLiteral || expression is NullConstant) {
5510+
result = inferenceVisitor.engine.forest.createEqualsNull(
5511+
fileOffset,
5512+
inferenceVisitor.engine.forest
5513+
.createVariableGet(fileOffset, matchedExpressionVariable));
5514+
} else {
5515+
ObjectAccessTarget target = inferenceVisitor.findInterfaceMember(
5516+
receiverType, equalsName, fileOffset,
5517+
callSiteAccessKind: CallSiteAccessKind.operatorInvocation);
5518+
result = inferenceVisitor.engine.forest.createEqualsCall(
5519+
fileOffset,
5520+
inferenceVisitor.engine.forest
5521+
.createVariableGet(fileOffset, matchedExpressionVariable),
5522+
expression,
5523+
target.getFunctionType(inferenceVisitor),
5524+
target.member as Procedure);
5525+
}
5526+
if (kind == RelationalPatternKind.notEquals) {
5527+
result = inferenceVisitor.engine.forest.createNot(fileOffset, result);
5528+
}
5529+
return result;
5530+
case RelationalPatternKind.lessThan:
5531+
name = lessThanName;
5532+
break;
5533+
case RelationalPatternKind.lessThanEqual:
5534+
name = lessThanOrEqualsName;
5535+
break;
5536+
case RelationalPatternKind.greaterThan:
5537+
name = greaterThanName;
5538+
break;
5539+
case RelationalPatternKind.greaterThanEqual:
5540+
name = greaterThanOrEqualsName;
5541+
break;
5542+
}
5543+
ObjectAccessTarget target = inferenceVisitor.findInterfaceMember(
5544+
receiverType, name, fileOffset,
5545+
callSiteAccessKind: CallSiteAccessKind.operatorInvocation);
5546+
if (target.kind == ObjectAccessTargetKind.dynamic) {
5547+
return new DynamicInvocation(
5548+
DynamicAccessKind.Dynamic,
5549+
inferenceVisitor.engine.forest
5550+
.createVariableGet(fileOffset, matchedExpressionVariable),
5551+
name,
5552+
inferenceVisitor.engine.forest
5553+
.createArguments(fileOffset, [expression]));
5554+
} else if (target.member is! Procedure) {
5555+
inferenceVisitor.helper.addProblem(
5556+
templateUndefinedOperator.withArguments(
5557+
name.text, receiverType, inferenceVisitor.isNonNullableByDefault),
5558+
matchedExpressionVariable.fileOffset,
5559+
noLength);
5560+
return null;
5561+
} else {
5562+
return new InstanceInvocation(
5563+
InstanceAccessKind.Instance,
5564+
inferenceVisitor.engine.forest
5565+
.createVariableGet(fileOffset, matchedExpressionVariable),
5566+
name,
5567+
inferenceVisitor.engine.forest
5568+
.createArguments(fileOffset, [expression]),
5569+
functionType: target.getFunctionType(inferenceVisitor),
5570+
interfaceTarget: target.member as Procedure)
5571+
..fileOffset = fileOffset;
5572+
}
55045573
}
55055574

55065575
@override

pkg/front_end/lib/src/fasta/type_inference/inference_visitor.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7856,7 +7856,9 @@ class InferenceVisitorImpl extends InferenceVisitorBase
78567856
required Map<VariableDeclaration, VariableTypeInfo<Node, DartType>>
78577857
typeInfos,
78587858
required MatchContext<Node, Expression> context}) {
7859-
// TODO(cstefantsova): Should the expression be inferred?
7859+
ExpressionInferenceResult expressionResult =
7860+
inferExpression(matcher.expression, matchedType, true);
7861+
matcher.expression = expressionResult.expression..parent = matcher;
78607862
return const PatternInferenceResult();
78617863
}
78627864

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
15
test(dynamic x) {
26
if (x case == 1) {}
7+
if (x case == null) {}
8+
if (x case == 'foo'.length) {}
9+
if (x case != 1) {}
10+
if (x case != null) {}
11+
if (x case < 1) {}
12+
if (x case <= 1) {}
13+
if (x case > 1) {}
14+
if (x case >= 1) {}
315
}
16+
17+
main() {}
Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,34 @@
11
library /*isNonNullableByDefault*/;
22
import self as self;
3+
import "dart:core" as core;
34

45
static method test(dynamic x) → dynamic {
56
final dynamic #t1 = x;
6-
if(invalid-expression "Unimplemented RelationalMatcher.makeCondition") {
7+
if(#t1 =={core::Object::==}{(core::Object) → core::bool} 1) {
8+
}
9+
final dynamic #t2 = x;
10+
if(#t2 == null) {
11+
}
12+
final dynamic #t3 = x;
13+
if(#t3 =={core::Object::==}{(core::Object) → core::bool} "foo".{core::String::length}{core::int}) {
14+
}
15+
final dynamic #t4 = x;
16+
if(!(#t4 =={core::Object::==}{(core::Object) → core::bool} 1)) {
17+
}
18+
final dynamic #t5 = x;
19+
if(!(#t5 == null)) {
20+
}
21+
final dynamic #t6 = x;
22+
if(#t6{dynamic}.<(1)) {
23+
}
24+
final dynamic #t7 = x;
25+
if(#t7{dynamic}.<=(1)) {
26+
}
27+
final dynamic #t8 = x;
28+
if(#t8{dynamic}.>(1)) {
29+
}
30+
final dynamic #t9 = x;
31+
if(#t9{dynamic}.>=(1)) {
732
}
833
}
34+
static method main() → dynamic {}
Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,39 @@
11
library /*isNonNullableByDefault*/;
22
import self as self;
3+
import "dart:core" as core;
34

45
static method test(dynamic x) → dynamic {
56
final dynamic #t1 = x;
6-
if(invalid-expression "Unimplemented RelationalMatcher.makeCondition") {
7+
if(#t1 =={core::Object::==}{(core::Object) → core::bool} 1) {
8+
}
9+
final dynamic #t2 = x;
10+
if(#t2 == null) {
11+
}
12+
final dynamic #t3 = x;
13+
if(#t3 =={core::Object::==}{(core::Object) → core::bool} "foo".{core::String::length}{core::int}) {
14+
}
15+
final dynamic #t4 = x;
16+
if(!(#t4 =={core::Object::==}{(core::Object) → core::bool} 1)) {
17+
}
18+
final dynamic #t5 = x;
19+
if(!(#t5 == null)) {
20+
}
21+
final dynamic #t6 = x;
22+
if(#t6{dynamic}.<(1)) {
23+
}
24+
final dynamic #t7 = x;
25+
if(#t7{dynamic}.<=(1)) {
26+
}
27+
final dynamic #t8 = x;
28+
if(#t8{dynamic}.>(1)) {
29+
}
30+
final dynamic #t9 = x;
31+
if(#t9{dynamic}.>=(1)) {
732
}
833
}
34+
static method main() → dynamic {}
35+
36+
37+
Extra constant evaluation status:
38+
Evaluated: InstanceGet @ org-dartlang-testcase:///relational_inside_if_case.dart:8:23 -> IntConstant(3)
39+
Extra constant evaluation: evaluated: 30, effectively constant: 1
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
test(dynamic x) {}
2+
main() {}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
main() {}
12
test(dynamic x) {}
Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,34 @@
11
library /*isNonNullableByDefault*/;
22
import self as self;
3+
import "dart:core" as core;
34

45
static method test(dynamic x) → dynamic {
56
final dynamic #t1 = x;
6-
if(invalid-expression "Unimplemented RelationalMatcher.makeCondition") {
7+
if(#t1 =={core::Object::==}{(core::Object) → core::bool} 1) {
8+
}
9+
final dynamic #t2 = x;
10+
if(#t2 == null) {
11+
}
12+
final dynamic #t3 = x;
13+
if(#t3 =={core::Object::==}{(core::Object) → core::bool} "foo".{core::String::length}{core::int}) {
14+
}
15+
final dynamic #t4 = x;
16+
if(!(#t4 =={core::Object::==}{(core::Object) → core::bool} 1)) {
17+
}
18+
final dynamic #t5 = x;
19+
if(!(#t5 == null)) {
20+
}
21+
final dynamic #t6 = x;
22+
if(#t6{dynamic}.<(1)) {
23+
}
24+
final dynamic #t7 = x;
25+
if(#t7{dynamic}.<=(1)) {
26+
}
27+
final dynamic #t8 = x;
28+
if(#t8{dynamic}.>(1)) {
29+
}
30+
final dynamic #t9 = x;
31+
if(#t9{dynamic}.>=(1)) {
732
}
833
}
34+
static method main() → dynamic {}
Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,34 @@
11
library /*isNonNullableByDefault*/;
22
import self as self;
3+
import "dart:core" as core;
34

45
static method test(dynamic x) → dynamic {
56
final dynamic #t1 = x;
6-
if(invalid-expression "Unimplemented RelationalMatcher.makeCondition") {
7+
if(#t1 =={core::Object::==}{(core::Object) → core::bool} 1) {
8+
}
9+
final dynamic #t2 = x;
10+
if(#t2 == null) {
11+
}
12+
final dynamic #t3 = x;
13+
if(#t3 =={core::Object::==}{(core::Object) → core::bool} "foo".{core::String::length}{core::int}) {
14+
}
15+
final dynamic #t4 = x;
16+
if(!(#t4 =={core::Object::==}{(core::Object) → core::bool} 1)) {
17+
}
18+
final dynamic #t5 = x;
19+
if(!(#t5 == null)) {
20+
}
21+
final dynamic #t6 = x;
22+
if(#t6{dynamic}.<(1)) {
23+
}
24+
final dynamic #t7 = x;
25+
if(#t7{dynamic}.<=(1)) {
26+
}
27+
final dynamic #t8 = x;
28+
if(#t8{dynamic}.>(1)) {
29+
}
30+
final dynamic #t9 = x;
31+
if(#t9{dynamic}.>=(1)) {
732
}
833
}
34+
static method main() → dynamic {}

pkg/front_end/testcases/patterns/relational_inside_if_case.dart.weak.outline.expect

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ import self as self;
33

44
static method test(dynamic x) → dynamic
55
;
6+
static method main() → dynamic
7+
;
Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,39 @@
11
library /*isNonNullableByDefault*/;
22
import self as self;
3+
import "dart:core" as core;
34

45
static method test(dynamic x) → dynamic {
56
final dynamic #t1 = x;
6-
if(invalid-expression "Unimplemented RelationalMatcher.makeCondition") {
7+
if(#t1 =={core::Object::==}{(core::Object) → core::bool} 1) {
8+
}
9+
final dynamic #t2 = x;
10+
if(#t2 == null) {
11+
}
12+
final dynamic #t3 = x;
13+
if(#t3 =={core::Object::==}{(core::Object) → core::bool} "foo".{core::String::length}{core::int}) {
14+
}
15+
final dynamic #t4 = x;
16+
if(!(#t4 =={core::Object::==}{(core::Object) → core::bool} 1)) {
17+
}
18+
final dynamic #t5 = x;
19+
if(!(#t5 == null)) {
20+
}
21+
final dynamic #t6 = x;
22+
if(#t6{dynamic}.<(1)) {
23+
}
24+
final dynamic #t7 = x;
25+
if(#t7{dynamic}.<=(1)) {
26+
}
27+
final dynamic #t8 = x;
28+
if(#t8{dynamic}.>(1)) {
29+
}
30+
final dynamic #t9 = x;
31+
if(#t9{dynamic}.>=(1)) {
732
}
833
}
34+
static method main() → dynamic {}
35+
36+
37+
Extra constant evaluation status:
38+
Evaluated: InstanceGet @ org-dartlang-testcase:///relational_inside_if_case.dart:8:23 -> IntConstant(3)
39+
Extra constant evaluation: evaluated: 30, effectively constant: 1

0 commit comments

Comments
 (0)