Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(367)

Side by Side Diff: pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart

Issue 2944903002: Implement type inference for if-null expressions (a ?? b). (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /// This file declares a "shadow hierarchy" of concrete classes which extend 5 /// This file declares a "shadow hierarchy" of concrete classes which extend
6 /// the kernel class hierarchy, adding methods and fields needed by the 6 /// the kernel class hierarchy, adding methods and fields needed by the
7 /// BodyBuilder. 7 /// BodyBuilder.
8 /// 8 ///
9 /// Instances of these classes may be created using the factory methods in 9 /// Instances of these classes may be created using the factory methods in
10 /// `ast_factory.dart`. 10 /// `ast_factory.dart`.
(...skipping 917 matching lines...) Expand 10 before | Expand all | Expand 10 after
928 'returnType', new InstrumentationValueForType(inferredReturnType)); 928 'returnType', new InstrumentationValueForType(inferredReturnType));
929 function.returnType = inferredReturnType; 929 function.returnType = inferredReturnType;
930 } 930 }
931 inferrer.closureContext = oldClosureContext; 931 inferrer.closureContext = oldClosureContext;
932 var inferredType = typeNeeded ? function.functionType : null; 932 var inferredType = typeNeeded ? function.functionType : null;
933 inferrer.listener.functionExpressionExit(this, inferredType); 933 inferrer.listener.functionExpressionExit(this, inferredType);
934 return inferredType; 934 return inferredType;
935 } 935 }
936 } 936 }
937 937
938 /// Concrete shadow object representing an if-null expression.
939 ///
940 /// An if-null expression of the form `a ?? b` is represented as the kernel
941 /// expression:
942 ///
943 /// let v = a in v == null ? b : v
944 class KernelIfNullExpression extends Let implements KernelExpression {
945 KernelIfNullExpression(VariableDeclaration variable, Expression body)
946 : super(variable, body);
947
948 @override
949 ConditionalExpression get body => super.body;
950
951 /// Returns the expression to the left of `??`.
952 Expression get _lhs => variable.initializer;
953
954 /// Returns the expression to the right of `??`.
955 Expression get _rhs => body.then;
956
957 @override
958 void _collectDependencies(KernelDependencyCollector collector) {
959 // If-null expressions are not immediately evident expressions.
960 collector.recordNotImmediatelyEvident(fileOffset);
961 }
962
963 @override
964 DartType _inferExpression(
965 KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
966 typeNeeded = inferrer.listener.ifNullEnter(this, typeContext) || typeNeeded;
967 // To infer `e0 ?? e1` in context K:
968 // - Infer e0 in context K to get T0
969 var lhsType = inferrer.inferExpression(_lhs, typeContext, true);
970 variable.type = lhsType;
971 // - Let J = T0 if K is `_` else K.
972 var rhsContext = typeContext ?? lhsType;
973 // - Infer e1 in context J to get T1
974 var rhsType =
975 inferrer.inferExpression(_rhs, rhsContext, typeContext == null);
976 // - Let T = greatest closure of K with respect to `?` if K is not `_`, else
977 // UP(t0, t1)
978 // - Then the inferred type is T.
979 var inferredType = typeContext == null
980 ? inferrer.typeSchemaEnvironment.getLeastUpperBound(lhsType, rhsType)
981 : greatestClosure(inferrer.coreTypes, typeContext);
982 body.staticType = inferredType;
983 inferrer.listener.ifNullExit(this, inferredType);
984 return inferredType;
985 }
986 }
987
938 /// Concrete shadow object representing an if statement in kernel form. 988 /// Concrete shadow object representing an if statement in kernel form.
939 class KernelIfStatement extends IfStatement implements KernelStatement { 989 class KernelIfStatement extends IfStatement implements KernelStatement {
940 KernelIfStatement(Expression condition, Statement then, Statement otherwise) 990 KernelIfStatement(Expression condition, Statement then, Statement otherwise)
941 : super(condition, then, otherwise); 991 : super(condition, then, otherwise);
942 992
943 @override 993 @override
944 void _inferStatement(KernelTypeInferrer inferrer) { 994 void _inferStatement(KernelTypeInferrer inferrer) {
945 inferrer.listener.ifStatementEnter(this); 995 inferrer.listener.ifStatementEnter(this);
946 inferrer.inferExpression( 996 inferrer.inferExpression(
947 condition, inferrer.coreTypes.boolClass.rawType, false); 997 condition, inferrer.coreTypes.boolClass.rawType, false);
(...skipping 1273 matching lines...) Expand 10 before | Expand all | Expand 10 after
2221 } 2271 }
2222 2272
2223 transformChildren(v) { 2273 transformChildren(v) {
2224 return internalError("Internal error: Unsupported operation."); 2274 return internalError("Internal error: Unsupported operation.");
2225 } 2275 }
2226 2276
2227 visitChildren(v) { 2277 visitChildren(v) {
2228 return internalError("Internal error: Unsupported operation."); 2278 return internalError("Internal error: Unsupported operation.");
2229 } 2279 }
2230 } 2280 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698