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

Side by Side Diff: pkg/front_end/lib/src/fasta/builder/shadow_ast.dart

Issue 2768533002: Fasta type inference prototype #2
Patch Set: Rework atop 415c868589d02e98eb839f48150f4203d5cecdb0 Created 3 years, 9 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 import 'package:front_end/src/fasta/type_inference/local_type_inferrer.dart';
6
5 /// This file declares mixins which can be used to create a shadow hierarchy 7 /// This file declares mixins which can be used to create a shadow hierarchy
6 /// of either the kernel or the analyzer AST representations. 8 /// of either the kernel or the analyzer AST representations.
7 /// 9 ///
8 /// These classes are intended to be used by [BodyBuilder] as a form of 10 /// These classes are intended to be used by [BodyBuilder] as a form of
9 /// indirection so that it can manipulate either kernel or analyzer ASTs. 11 /// indirection so that it can manipulate either kernel or analyzer ASTs.
10 /// 12 ///
11 /// All methods, getters, and setters defined in this file start with the prefix 13 /// All methods, getters, and setters defined in this file start with the prefix
12 /// "shadow" in order to avoid naming conflicts with code in kernel or analyzer. 14 /// "shadow" in order to avoid naming conflicts with code in kernel or analyzer.
13 /// 15 ///
14 /// Note that the analyzer AST representation closely parallels Dart syntax, 16 /// Note that the analyzer AST representation closely parallels Dart syntax,
15 /// whereas the kernel AST representation is desugared. The classes in the 17 /// whereas the kernel AST representation is desugared. The classes in the
16 /// shadow hierarchy represent the full language (prior to desugaring). 18 /// shadow hierarchy represent the full language (prior to desugaring).
17 import 'package:kernel/ast.dart' show DartType; 19 import 'package:kernel/ast.dart' show DartType, DynamicType, InterfaceType;
20 import 'package:kernel/core_types.dart';
18 21
19 /// Shadow mixin representing a statement block. 22 /// Shadow mixin representing a statement block.
20 abstract class ShadowBlock implements ShadowStatement { 23 abstract class ShadowBlock implements ShadowStatement {
21 /// Iterates through the statements contained in the block. 24 /// Iterates through the statements contained in the block.
22 Iterable<ShadowStatement> get shadowStatements; 25 Iterable<ShadowStatement> get shadowStatements;
26
27 @override
28 void shadowInfer(LocalTypeInferrer inferrer, FunctionContext context) {
29 for (var statement in shadowStatements) {
30 statement.shadowInfer(inferrer, context);
31 }
32 }
23 } 33 }
24 34
25 /// Common interface for shadow mixins representing expressions. 35 /// Common interface for shadow mixins representing expressions.
26 /// 36 abstract class ShadowExpression {
27 /// TODO(paulberry): add an abstract `shadowInfer` method here to do type 37 DartType shadowInfer(
28 /// inference. 38 LocalTypeInferrer inferrer, DartType context, bool typeNeeded);
29 abstract class ShadowExpression {} 39 }
30 40
31 /// Shadow mixin representing a function expression. 41 /// Shadow mixin representing a function expression.
32 abstract class ShadowFunctionExpression implements ShadowExpression { 42 abstract class ShadowFunctionExpression implements ShadowExpression {
33 /// Gets the body of the function expression. 43 /// Gets the body of the function expression.
34 ShadowStatement get shadowBody; 44 ShadowStatement get shadowBody;
35 45
36 /// Creates a [DartType] representing the type of the function expression. 46 /// Creates a [DartType] representing the type of the function expression.
37 /// 47 ///
38 /// If type inference has already been performed, returns the inferred type. 48 /// If type inference has already been performed, returns the inferred type.
39 /// Otherwise returns the declared type. 49 /// Otherwise returns the declared type.
40 DartType get shadowFunctionType; 50 DartType get shadowFunctionType;
41 51
42 /// Indicates whether the function is asynchronous (`async` or `async*`) 52 /// Indicates whether the function is asynchronous (`async` or `async*`)
43 bool get shadowIsAsync; 53 bool get shadowIsAsync;
44 54
45 /// Indicates whether the function was declared using `=>` syntax. 55 /// Indicates whether the function was declared using `=>` syntax.
46 bool get shadowIsExpressionFunction; 56 bool get shadowIsExpressionFunction;
47 57
48 /// Indicates whether the function is a generator (`sync*` or `async*`) 58 /// Indicates whether the function is a generator (`sync*` or `async*`)
49 bool get shadowIsGenerator; 59 bool get shadowIsGenerator;
50 60
51 /// Sets the return type of the function expression. 61 /// Sets the return type of the function expression.
52 /// 62 ///
53 /// Intended for use by type inference. 63 /// Intended for use by type inference.
54 void set shadowReturnType(DartType type); 64 void set shadowReturnType(DartType type);
65
66 @override
67 DartType shadowInfer(
68 LocalTypeInferrer inferrer, DartType context, bool typeNeeded) {
69 // TODO(paulberry): infer argument types and type parameters.
70 // TODO(paulberry): full support for generators.
71 var body = shadowBody;
72 // TODO(paulberry): Dart 1.0 rules say we only need to set the function
73 // node's return type if it uses expression syntax. Does that make sense
74 // for Dart 2.0?
75 bool needToSetReturnType = shadowIsExpressionFunction;
76 bool returnTypeNeeded = typeNeeded || needToSetReturnType;
77 bool isAsync = shadowIsAsync;
78 var functionContext = new FunctionContext(
79 inferrer, returnTypeNeeded, isAsync, shadowIsGenerator);
80 body.shadowInfer(inferrer, functionContext);
81 DartType inferredReturnType;
82 if (needToSetReturnType || typeNeeded) {
83 inferredReturnType = functionContext.inferredReturnType;
84 if (isAsync) {
85 inferredReturnType = new InterfaceType(
86 inferrer.coreTypes.futureClass, <DartType>[inferredReturnType]);
87 }
88 }
89 if (needToSetReturnType) {
90 this.shadowReturnType = inferredReturnType;
91 }
92 if (typeNeeded) {
93 return shadowFunctionType;
94 } else {
95 return null;
96 }
97 }
55 } 98 }
56 99
57 /// Shadow mixin representing an integer literal. 100 /// Shadow mixin representing an integer literal.
58 abstract class ShadowIntLiteral implements ShadowExpression {} 101 abstract class ShadowIntLiteral implements ShadowExpression {
102 @override
103 DartType shadowInfer(
104 LocalTypeInferrer inferrer, DartType context, bool typeNeeded) {
105 return typeNeeded ? inferrer.coreTypes.intClass.rawType : null;
106 }
107 }
59 108
60 /// Shadow mixin representing a list literal. 109 /// Shadow mixin representing a list literal.
61 abstract class ShadowListLiteral implements ShadowExpression { 110 abstract class ShadowListLiteral implements ShadowExpression {
62 /// Iterates through the expressions contained in the list literal. 111 /// Iterates through the expressions contained in the list literal.
63 Iterable<ShadowExpression> get shadowExpressions; 112 Iterable<ShadowExpression> get shadowExpressions;
64 113
65 /// Gets the type argument of the list literal. If type inference has not 114 /// Gets the type argument of the list literal. If type inference has not
66 /// been performed and no explicit type argument was specified, returns 115 /// been performed and no explicit type argument was specified, returns
67 /// `null`. 116 /// `null`.
68 DartType get shadowTypeArgument; 117 DartType get shadowTypeArgument;
69 118
70 /// Sets the type argument of the list literal. 119 /// Sets the type argument of the list literal.
71 /// 120 ///
72 /// Intended for use by type inference. 121 /// Intended for use by type inference.
73 void set shadowTypeArgument(DartType type); 122 void set shadowTypeArgument(DartType type);
123
124 @override
125 DartType shadowInfer(
126 LocalTypeInferrer inferrer, DartType context, bool typeNeeded) {
127 DartType declaredTypeArgument = shadowTypeArgument;
128 DartType typeArgumentContext = declaredTypeArgument;
129 if (typeArgumentContext == null) {
130 if (context is InterfaceType &&
131 context.classNode == inferrer.coreTypes.listClass &&
132 context.typeArguments.length == 1) {
133 typeArgumentContext = context.typeArguments[0];
134 } else if (context != null) {
135 // TODO(paulberry): report an error?
136 throw new UnimplementedError('$context');
137 }
138 }
139 DartType inferredTypeArgument = typeArgumentContext;
140 bool typeArgumentNeeded = inferredTypeArgument == null;
141 for (ShadowExpression e in shadowExpressions) {
142 DartType t =
143 e.shadowInfer(inferrer, typeArgumentContext, typeArgumentNeeded);
144 if (typeArgumentNeeded) {
145 inferredTypeArgument = inferrer.union(inferredTypeArgument, t);
146 }
147 }
148 if (inferredTypeArgument == null) {
149 // Empty list.
150 throw new UnimplementedError();
151 }
152 if (declaredTypeArgument == null) {
153 this.shadowTypeArgument = inferredTypeArgument;
154 }
155 if (typeNeeded) {
156 return new InterfaceType(
157 inferrer.coreTypes.listClass, <DartType>[inferredTypeArgument]);
158 } else {
159 return null;
160 }
161 }
74 } 162 }
75 163
76 /// Shadow mixin representing a null literal. 164 /// Shadow mixin representing a null literal.
77 abstract class ShadowNullLiteral implements ShadowExpression {} 165 abstract class ShadowNullLiteral implements ShadowExpression {
166 @override
167 DartType shadowInfer(
168 LocalTypeInferrer inferrer, DartType context, bool typeNeeded) {
169 return typeNeeded ? inferrer.coreTypes.nullClass.rawType : null;
170 }
171 }
78 172
79 /// Shadow mixin representing a return statement. 173 /// Shadow mixin representing a return statement.
80 abstract class ShadowReturnStatement implements ShadowStatement { 174 abstract class ShadowReturnStatement implements ShadowStatement {
81 /// Gets the expression being returned, or `null` if this is a bare "return" 175 /// Gets the expression being returned, or `null` if this is a bare "return"
82 /// statement. 176 /// statement.
83 ShadowExpression get shadowExpression; 177 ShadowExpression get shadowExpression;
178
179 @override
180 void shadowInfer(LocalTypeInferrer inferrer, FunctionContext context) {
181 DartType expressionContext = null; // TODO(paulberry): probably wrong.
182 bool expressionTypeNeeded =
183 context.returnTypeNeeded && !context.isGenerator;
184 DartType expressionType = shadowExpression.shadowInfer(
185 inferrer, expressionContext, expressionTypeNeeded);
186 if (expressionTypeNeeded) {
187 if (context.isAsync) {
188 expressionType = _unwrapFuture(inferrer.coreTypes, expressionType);
189 }
190 context.recordReturnType(expressionType);
191 }
192 }
193
194 DartType _unwrapFuture(CoreTypes coreTypes, DartType type) {
195 // TODO(paulberry): replace with a full implementation of what's in the spec
196 // (e.g. handle types derived from Future). Also probably move to Kernel.
197 if (type is InterfaceType && type.classNode == coreTypes.futureClass) {
198 return type.typeArguments[0];
199 } else {
200 return type;
201 }
202 }
84 } 203 }
85 204
86 /// Common interface for shadow mixins representing statements. 205 /// Common interface for shadow mixins representing statements.
87 /// 206 abstract class ShadowStatement {
88 /// TODO(paulberry): add an abstract `shadowInfer` method here to do type 207 void shadowInfer(LocalTypeInferrer inferrer, FunctionContext context);
89 /// inference. 208 }
90 abstract class ShadowStatement {}
91 209
92 /// Shadow mixin representing a declaration of a single variable. 210 /// Shadow mixin representing a declaration of a single variable.
93 abstract class ShadowVariableDeclaration implements ShadowStatement { 211 abstract class ShadowVariableDeclaration implements ShadowStatement {
94 /// Gets the initializer expression for the variable, or `null` if the 212 /// Gets the initializer expression for the variable, or `null` if the
95 /// variable has no initializer. 213 /// variable has no initializer.
96 ShadowExpression get shadowInitializer; 214 ShadowExpression get shadowInitializer;
97 215
98 /// Gets the type of the variable. If type inference has not been performed 216 /// Gets the type of the variable. If type inference has not been performed
99 /// and no explicit type was specified, returns `null`. 217 /// and no explicit type was specified, returns `null`.
100 DartType get shadowType; 218 DartType get shadowType;
101 219
102 /// Sets the type of the variable. 220 /// Sets the type of the variable.
103 /// 221 ///
104 /// Intended for use by type inference. 222 /// Intended for use by type inference.
105 void set shadowType(DartType type); 223 void set shadowType(DartType type);
224
225 @override
226 void shadowInfer(LocalTypeInferrer inferrer, FunctionContext context) {
227 var initializer = shadowInitializer;
228 if (initializer != null) {
229 var type = shadowType;
230 var inferredType = initializer.shadowInfer(inferrer, type, type == null);
231 if (type == null) {
232 this.shadowType = inferredType;
233 }
234 }
235 }
106 } 236 }
107 237
108 /// Shadow mixin representing a "read" reference to a variable. 238 /// Shadow mixin representing a "read" reference to a variable.
109 abstract class ShadowVariableGet implements ShadowExpression { 239 abstract class ShadowVariableGet implements ShadowExpression {
110 /// Gets the variable declaration which is being referenced. 240 /// Gets the variable declaration which is being referenced.
111 ShadowVariableDeclaration get shadowDeclaration; 241 ShadowVariableDeclaration get shadowDeclaration;
242
243 @override
244 DartType shadowInfer(
245 LocalTypeInferrer inferrer, DartType context, bool typeNeeded) {
246 // TODO(paulberry): make the "?? const DynamicType()" unnecessary.
247 return typeNeeded
248 ? (shadowDeclaration.shadowType ?? const DynamicType())
249 : null;
250 }
112 } 251 }
OLDNEW
« no previous file with comments | « pkg/front_end/lib/src/fasta/builder/ast_factory.dart ('k') | pkg/front_end/lib/src/fasta/kernel/body_builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698