OLD | NEW |
---|---|
(Empty) | |
1 import 'package:front_end/src/fasta/type_inference/local_type_inferrer.dart'; | |
2 import 'package:kernel/ast.dart' show DartType, InterfaceType; | |
3 import 'package:kernel/core_types.dart'; | |
4 | |
5 abstract class Block implements Statement { | |
6 Iterable<Statement> get shadowStatements; | |
7 | |
8 @override | |
9 void shadowInfer(LocalTypeInferrer inferrer, FunctionContext context) { | |
10 for (var statement in shadowStatements) { | |
11 statement.shadowInfer(inferrer, context); | |
12 } | |
13 } | |
14 } | |
15 | |
16 abstract class Expression { | |
17 DartType shadowInfer( | |
18 LocalTypeInferrer inferrer, DartType context, bool typeNeeded); | |
19 } | |
20 | |
21 abstract class FunctionExpression implements Expression { | |
22 void set shadowInferredReturnType(DartType type); | |
23 | |
24 Statement get shadowBody; | |
25 | |
26 bool get shadowIsAsync; | |
27 | |
28 bool get shadowIsExpressionFunction; | |
29 | |
30 bool get shadowIsGenerator; | |
31 | |
32 DartType shadowMakeFunctionType(); | |
33 | |
34 @override | |
35 DartType shadowInfer( | |
36 LocalTypeInferrer inferrer, DartType context, bool typeNeeded) { | |
37 // TODO(paulberry): infer argument types and type parameters. | |
38 // TODO(paulberry): full support for generators. | |
39 Statement body = shadowBody; | |
40 // TODO(paulberry): Dart 1.0 rules say we only need to set the function | |
41 // node's return type if it uses expression syntax. Does that make sense | |
42 // for Dart 2.0? | |
43 bool needToSetReturnType = shadowIsExpressionFunction; | |
44 bool returnTypeNeeded = typeNeeded || needToSetReturnType; | |
45 bool isAsync = shadowIsAsync; | |
46 var functionContext = new FunctionContext( | |
47 inferrer, returnTypeNeeded, isAsync, shadowIsGenerator); | |
48 body.shadowInfer(inferrer, functionContext); | |
49 DartType inferredReturnType; | |
50 if (needToSetReturnType || typeNeeded) { | |
51 inferredReturnType = functionContext.inferredReturnType; | |
52 if (isAsync) { | |
53 inferredReturnType = new InterfaceType( | |
54 inferrer.coreTypes.futureClass, <DartType>[inferredReturnType]); | |
55 } | |
56 } | |
57 if (needToSetReturnType) { | |
58 this.shadowInferredReturnType = inferredReturnType; | |
59 } | |
60 if (typeNeeded) { | |
61 return shadowMakeFunctionType(); | |
62 } else { | |
63 return null; | |
64 } | |
65 } | |
66 } | |
67 | |
68 abstract class IntLiteral implements Expression { | |
69 @override | |
70 DartType shadowInfer( | |
71 LocalTypeInferrer inferrer, DartType context, bool typeNeeded) { | |
72 return typeNeeded ? inferrer.coreTypes.intClass.rawType : null; | |
73 } | |
74 } | |
75 | |
76 abstract class ListLiteral implements Expression { | |
77 DartType get declaredTypeArgumentForInference; | |
78 | |
79 Iterable<Expression> get expressionsForInference; | |
80 | |
81 void set inferredTypeArgument(DartType type); | |
82 | |
83 @override | |
84 DartType shadowInfer( | |
85 LocalTypeInferrer inferrer, DartType context, bool typeNeeded) { | |
86 DartType declaredTypeArgument = declaredTypeArgumentForInference; | |
87 DartType typeArgumentContext = declaredTypeArgument; | |
88 if (typeArgumentContext == null) { | |
89 if (context is InterfaceType && | |
90 context.classNode == inferrer.coreTypes.listClass && | |
91 context.typeArguments.length == 1) { | |
92 typeArgumentContext = context.typeArguments[0]; | |
93 } else if (context != null) { | |
94 // TODO(paulberry): report an error? | |
95 throw new UnimplementedError('$context'); | |
scheglov
2017/03/24 15:38:10
If I understand correctly, "context" will be Itera
Paul Berry
2017/03/24 17:59:50
You are correct. This entire method is a hack tha
| |
96 } | |
97 } | |
98 DartType inferredTypeArgument = typeArgumentContext; | |
99 bool typeArgumentNeeded = inferredTypeArgument == null; | |
100 for (Expression e in expressionsForInference) { | |
101 DartType t = | |
102 e.shadowInfer(inferrer, typeArgumentContext, typeArgumentNeeded); | |
103 if (typeArgumentNeeded) { | |
104 inferredTypeArgument = inferrer.union(inferredTypeArgument, t); | |
105 } | |
106 } | |
107 if (inferredTypeArgument == null) { | |
108 // Empty list. | |
109 throw new UnimplementedError(); | |
110 } | |
111 if (declaredTypeArgument == null) { | |
112 this.inferredTypeArgument = inferredTypeArgument; | |
113 } | |
114 if (typeNeeded) { | |
115 return new InterfaceType( | |
116 inferrer.coreTypes.listClass, <DartType>[inferredTypeArgument]); | |
117 } else { | |
118 return null; | |
119 } | |
120 } | |
121 } | |
122 | |
123 abstract class NullLiteral implements Expression { | |
124 @override | |
125 DartType shadowInfer( | |
126 LocalTypeInferrer inferrer, DartType context, bool typeNeeded) { | |
127 return typeNeeded ? inferrer.coreTypes.nullClass.rawType : null; | |
128 } | |
129 } | |
130 | |
131 abstract class ReturnStatement implements Statement { | |
132 Expression get expressionForInference; | |
133 | |
134 @override | |
135 void shadowInfer(LocalTypeInferrer inferrer, FunctionContext context) { | |
136 DartType expressionContext = null; // TODO(paulberry): probably wrong. | |
137 bool expressionTypeNeeded = | |
138 context.returnTypeNeeded && !context.isGenerator; | |
139 DartType expressionType = expressionForInference.shadowInfer( | |
140 inferrer, expressionContext, expressionTypeNeeded); | |
141 if (expressionTypeNeeded) { | |
142 if (context.isAsync) { | |
143 expressionType = _unwrapFuture(inferrer.coreTypes, expressionType); | |
144 } | |
145 context.recordReturnType(expressionType); | |
146 } | |
147 } | |
148 | |
149 DartType _unwrapFuture(CoreTypes coreTypes, DartType type) { | |
150 // TODO(paulberry): replace with a full implementation of what's in the spec | |
151 // (e.g. handle types derived from Future). Also probably move to Kernel. | |
152 if (type is InterfaceType && type.classNode == coreTypes.futureClass) { | |
153 return type.typeArguments[0]; | |
154 } else { | |
155 return type; | |
156 } | |
157 } | |
158 } | |
159 | |
160 abstract class Statement { | |
161 void shadowInfer(LocalTypeInferrer inferrer, FunctionContext context); | |
162 } | |
163 | |
164 abstract class VariableDeclaration implements Statement { | |
165 DartType get shadowDeclaredType; | |
166 | |
167 DartType get shadowInferredType; | |
168 | |
169 void set shadowInferredType(DartType type); | |
170 | |
171 Expression get shadowInitializer; | |
172 | |
173 @override | |
174 void shadowInfer(LocalTypeInferrer inferrer, FunctionContext context) { | |
175 Expression initializer = shadowInitializer; | |
176 if (initializer != null) { | |
177 DartType type = shadowDeclaredType; | |
178 DartType inferredType = | |
179 initializer.shadowInfer(inferrer, type, type == null); | |
180 if (type == null) { | |
181 this.shadowInferredType = inferredType; | |
182 } | |
183 } | |
184 } | |
185 } | |
186 | |
187 abstract class VariableGet implements Expression { | |
188 VariableDeclaration get shadowDeclaration; | |
189 | |
190 @override | |
191 DartType shadowInfer( | |
192 LocalTypeInferrer inferrer, DartType context, bool typeNeeded) { | |
193 return typeNeeded ? shadowDeclaration.shadowInferredType : null; | |
194 } | |
195 } | |
OLD | NEW |