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

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

Issue 2903243002: Add type inference logic for cascade expressions. (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`.
11 /// 11 ///
12 /// Note that these classes represent the Dart language prior to desugaring. 12 /// Note that these classes represent the Dart language prior to desugaring.
13 /// When a single Dart construct desugars to a tree containing multiple kernel 13 /// When a single Dart construct desugars to a tree containing multiple kernel
14 /// AST nodes, the shadow class extends the kernel object at the top of the 14 /// AST nodes, the shadow class extends the kernel object at the top of the
15 /// desugared tree. 15 /// desugared tree.
16 /// 16 ///
17 /// This means that in some cases multiple shadow classes may extend the same 17 /// This means that in some cases multiple shadow classes may extend the same
18 /// kernel class, because multiple constructs in Dart may desugar to a tree 18 /// kernel class, because multiple constructs in Dart may desugar to a tree
19 /// with the same kind of root node. 19 /// with the same kind of root node.
20 import 'package:front_end/src/base/instrumentation.dart'; 20 import 'package:front_end/src/base/instrumentation.dart';
21 import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart'; 21 import 'package:front_end/src/fasta/type_inference/type_inference_engine.dart';
22 import 'package:front_end/src/fasta/type_inference/type_inference_listener.dart' ; 22 import 'package:front_end/src/fasta/type_inference/type_inference_listener.dart' ;
23 import 'package:front_end/src/fasta/type_inference/type_inferrer.dart'; 23 import 'package:front_end/src/fasta/type_inference/type_inferrer.dart';
24 import 'package:front_end/src/fasta/type_inference/type_promotion.dart'; 24 import 'package:front_end/src/fasta/type_inference/type_promotion.dart';
25 import 'package:front_end/src/fasta/type_inference/type_schema.dart'; 25 import 'package:front_end/src/fasta/type_inference/type_schema.dart';
26 import 'package:front_end/src/fasta/type_inference/type_schema_elimination.dart' ; 26 import 'package:front_end/src/fasta/type_inference/type_schema_elimination.dart' ;
27 import 'package:kernel/ast.dart'; 27 import 'package:kernel/ast.dart';
28 import 'package:kernel/frontend/accessors.dart';
28 import 'package:kernel/type_algebra.dart'; 29 import 'package:kernel/type_algebra.dart';
29 30
30 List<DartType> getExplicitTypeArguments(Arguments arguments) { 31 List<DartType> getExplicitTypeArguments(Arguments arguments) {
31 if (arguments is KernelArguments) { 32 if (arguments is KernelArguments) {
32 return arguments._hasExplicitTypeArguments ? arguments.types : null; 33 return arguments._hasExplicitTypeArguments ? arguments.types : null;
33 } else { 34 } else {
34 // This code path should only be taken in situations where there are no 35 // This code path should only be taken in situations where there are no
35 // type arguments at all, e.g. calling a user-definable operator. 36 // type arguments at all, e.g. calling a user-definable operator.
36 assert(arguments.types.isEmpty); 37 assert(arguments.types.isEmpty);
37 return null; 38 return null;
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
106 DartType _inferExpression( 107 DartType _inferExpression(
107 KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) { 108 KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
108 typeNeeded = 109 typeNeeded =
109 inferrer.listener.boolLiteralEnter(this, typeContext) || typeNeeded; 110 inferrer.listener.boolLiteralEnter(this, typeContext) || typeNeeded;
110 var inferredType = typeNeeded ? inferrer.coreTypes.boolClass.rawType : null; 111 var inferredType = typeNeeded ? inferrer.coreTypes.boolClass.rawType : null;
111 inferrer.listener.boolLiteralExit(this, inferredType); 112 inferrer.listener.boolLiteralExit(this, inferredType);
112 return inferredType; 113 return inferredType;
113 } 114 }
114 } 115 }
115 116
117 /// Concrete shadow object representing a cascade expression.
118 ///
119 /// A cascade expression of the form `a..b()..c()` is represented as the kernel
120 /// expression:
121 ///
122 /// let v = a in
123 /// let _ = v.b() in
124 /// let _ = v.c() in
125 /// v
126 ///
127 /// In the documentation that follows, `v` is referred to as the "cascade
128 /// variable"--this is the variable that remembers the value of the expression
129 /// preceding the first `..` while the cascades are being evaluated.
130 ///
131 /// After constructing a [KernelCascadeExpression], the caller should
132 /// call [finalize] with an expression representing the expression after the
133 /// `..`. If a further `..` follows that expression, the caller should call
134 /// [extend] followed by [finalize] for each subsequent cascade.
135 class KernelCascadeExpression extends Let implements KernelExpression {
136 /// Pointer to the last "let" expression in the cascade.
137 Let nextCascade;
138
139 /// Creates a [KernelCascadeExpression] using [variable] as the cascade
140 /// variable. Caller is responsible for ensuring that [variable]'s
141 /// initializer is the expression preceding the first `..` of the cascade
142 /// expression.
143 KernelCascadeExpression(KernelVariableDeclaration variable)
144 : super(
145 variable,
146 makeLet(new VariableDeclaration.forValue(new InvalidExpression()),
147 new VariableGet(variable))) {
148 nextCascade = body;
149 }
150
151 /// Adds a new unfinalized section to the end of the cascade. Should be
152 /// called after the previous cascade section has been finalized.
153 void extend() {
154 assert(nextCascade.variable.initializer is! InvalidExpression);
155 Let newCascade = makeLet(
156 new VariableDeclaration.forValue(new InvalidExpression()),
157 nextCascade.body);
158 nextCascade.body = newCascade;
159 newCascade.parent = nextCascade;
160 nextCascade = newCascade;
161 }
162
163 /// Finalizes the last cascade section with the given [expression].
164 void finalize(Expression expression) {
165 assert(nextCascade.variable.initializer is InvalidExpression);
166 nextCascade.variable.initializer = expression;
167 expression.parent = nextCascade.variable;
168 }
169
170 @override
171 DartType _inferExpression(
172 KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
173 typeNeeded = inferrer.listener.cascadeExpressionEnter(this, typeContext) ||
174 typeNeeded;
175 var lhsType = inferrer.inferExpression(
176 variable.initializer, typeContext, typeNeeded || inferrer.strongMode);
177 if (inferrer.strongMode) {
178 variable.type = lhsType;
179 }
180 Let section = body;
181 while (true) {
182 inferrer.inferExpression(section.variable.initializer, null, false);
183 if (section.body is! Let) break;
184 section = section.body;
185 }
186 inferrer.listener.cascadeExpressionExit(this, lhsType);
187 return lhsType;
188 }
189 }
190
116 /// Concrete shadow object representing a conditional expression in kernel form. 191 /// Concrete shadow object representing a conditional expression in kernel form.
117 /// Shadow object for [ConditionalExpression]. 192 /// Shadow object for [ConditionalExpression].
118 class KernelConditionalExpression extends ConditionalExpression 193 class KernelConditionalExpression extends ConditionalExpression
119 implements KernelExpression { 194 implements KernelExpression {
120 KernelConditionalExpression( 195 KernelConditionalExpression(
121 Expression condition, Expression then, Expression otherwise) 196 Expression condition, Expression then, Expression otherwise)
122 : super(condition, then, otherwise, const DynamicType()); 197 : super(condition, then, otherwise, const DynamicType());
123 198
124 @override 199 @override
125 DartType _inferExpression( 200 DartType _inferExpression(
(...skipping 1097 matching lines...) Expand 10 before | Expand all | Expand 10 after
1223 bool isConst: false, 1298 bool isConst: false,
1224 bool isLocalFunction: false}) 1299 bool isLocalFunction: false})
1225 : _implicitlyTyped = type == null, 1300 : _implicitlyTyped = type == null,
1226 _isLocalFunction = isLocalFunction, 1301 _isLocalFunction = isLocalFunction,
1227 super(name, 1302 super(name,
1228 initializer: initializer, 1303 initializer: initializer,
1229 type: type ?? const DynamicType(), 1304 type: type ?? const DynamicType(),
1230 isFinal: isFinal, 1305 isFinal: isFinal,
1231 isConst: isConst); 1306 isConst: isConst);
1232 1307
1308 KernelVariableDeclaration.forValue(
1309 Expression initializer, this._functionNestingLevel)
1310 : _implicitlyTyped = true,
1311 _isLocalFunction = false,
1312 super.forValue(initializer);
1313
1233 @override 1314 @override
1234 void _inferStatement(KernelTypeInferrer inferrer) { 1315 void _inferStatement(KernelTypeInferrer inferrer) {
1235 inferrer.listener.variableDeclarationEnter(this); 1316 inferrer.listener.variableDeclarationEnter(this);
1236 var declaredType = _implicitlyTyped ? null : type; 1317 var declaredType = _implicitlyTyped ? null : type;
1237 if (initializer != null) { 1318 if (initializer != null) {
1238 var inferredType = inferrer.inferDeclarationType(inferrer.inferExpression( 1319 var inferredType = inferrer.inferDeclarationType(inferrer.inferExpression(
1239 initializer, declaredType, _implicitlyTyped)); 1320 initializer, declaredType, _implicitlyTyped));
1240 if (inferrer.strongMode && _implicitlyTyped) { 1321 if (inferrer.strongMode && _implicitlyTyped) {
1241 inferrer.instrumentation?.record(Uri.parse(inferrer.uri), fileOffset, 1322 inferrer.instrumentation?.record(Uri.parse(inferrer.uri), fileOffset,
1242 'type', new InstrumentationValueForType(inferredType)); 1323 'type', new InstrumentationValueForType(inferredType));
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1321 closureContext.isAsync 1402 closureContext.isAsync
1322 ? inferrer.coreTypes.streamClass 1403 ? inferrer.coreTypes.streamClass
1323 : inferrer.coreTypes.iterableClass); 1404 : inferrer.coreTypes.iterableClass);
1324 } 1405 }
1325 var inferredType = inferrer.inferExpression( 1406 var inferredType = inferrer.inferExpression(
1326 expression, typeContext, closureContext != null); 1407 expression, typeContext, closureContext != null);
1327 closureContext.handleYield(inferrer, isYieldStar, inferredType); 1408 closureContext.handleYield(inferrer, isYieldStar, inferredType);
1328 inferrer.listener.yieldStatementExit(this); 1409 inferrer.listener.yieldStatementExit(this);
1329 } 1410 }
1330 } 1411 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698