OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 // TODO(johnniwinther): Remove this library when all constant constructors are | 5 // TODO(johnniwinther): Remove this library when all constant constructors are |
6 // computed during resolution. | 6 // computed during resolution. |
7 library dart2js.constants.constant_constructors; | 7 library dart2js.constants.constant_constructors; |
8 | 8 |
9 import '../common.dart'; | 9 import '../common.dart'; |
10 import '../dart_types.dart'; | 10 import '../dart_types.dart'; |
11 import '../elements/elements.dart'; | 11 import '../elements/elements.dart'; |
12 import '../resolution/operators.dart'; | 12 import '../resolution/operators.dart'; |
13 import '../resolution/semantic_visitor.dart'; | 13 import '../resolution/semantic_visitor.dart'; |
14 import '../resolution/send_resolver.dart' show | 14 import '../resolution/send_resolver.dart' show DeclarationResolverMixin; |
15 DeclarationResolverMixin; | |
16 import '../resolution/send_structure.dart'; | 15 import '../resolution/send_structure.dart'; |
17 import '../resolution/tree_elements.dart' show | 16 import '../resolution/tree_elements.dart' show TreeElements; |
18 TreeElements; | |
19 import '../tree/tree.dart'; | 17 import '../tree/tree.dart'; |
20 import '../universe/call_structure.dart' show | 18 import '../universe/call_structure.dart' show CallStructure; |
21 CallStructure; | |
22 | 19 |
23 import 'constructors.dart'; | 20 import 'constructors.dart'; |
24 import 'expressions.dart'; | 21 import 'expressions.dart'; |
25 | 22 |
26 ConstantConstructor computeConstantConstructor(ResolvedAst resolvedAst) { | 23 ConstantConstructor computeConstantConstructor(ResolvedAst resolvedAst) { |
27 ConstantConstructorComputer visitor = | 24 ConstantConstructorComputer visitor = |
28 new ConstantConstructorComputer(resolvedAst.elements); | 25 new ConstantConstructorComputer(resolvedAst.elements); |
29 return resolvedAst.node.accept(visitor); | 26 return resolvedAst.node.accept(visitor); |
30 } | 27 } |
31 | 28 |
32 class ConstantConstructorComputer extends SemanticVisitor | 29 class ConstantConstructorComputer extends SemanticVisitor |
33 with SemanticDeclarationResolvedMixin, | 30 with |
34 DeclarationResolverMixin, | 31 SemanticDeclarationResolvedMixin, |
35 GetBulkMixin, | 32 DeclarationResolverMixin, |
36 SetBulkMixin, | 33 GetBulkMixin, |
37 ErrorBulkMixin, | 34 SetBulkMixin, |
38 InvokeBulkMixin, | 35 ErrorBulkMixin, |
39 IndexSetBulkMixin, | 36 InvokeBulkMixin, |
40 CompoundBulkMixin, | 37 IndexSetBulkMixin, |
41 SetIfNullBulkMixin, | 38 CompoundBulkMixin, |
42 UnaryBulkMixin, | 39 SetIfNullBulkMixin, |
43 BaseBulkMixin, | 40 UnaryBulkMixin, |
44 BinaryBulkMixin, | 41 BaseBulkMixin, |
45 PrefixBulkMixin, | 42 BinaryBulkMixin, |
46 PostfixBulkMixin, | 43 PrefixBulkMixin, |
47 NewBulkMixin, | 44 PostfixBulkMixin, |
48 InitializerBulkMixin, | 45 NewBulkMixin, |
49 FunctionBulkMixin, | 46 InitializerBulkMixin, |
50 VariableBulkMixin | 47 FunctionBulkMixin, |
| 48 VariableBulkMixin |
51 implements SemanticDeclarationVisitor, SemanticSendVisitor { | 49 implements SemanticDeclarationVisitor, SemanticSendVisitor { |
52 final Map<FieldElement, ConstantExpression> fieldMap = | 50 final Map<FieldElement, ConstantExpression> fieldMap = |
53 <FieldElement, ConstantExpression>{}; | 51 <FieldElement, ConstantExpression>{}; |
54 final Map<dynamic/*int|String*/, ConstantExpression> defaultValues = | 52 final Map<dynamic /*int|String*/, ConstantExpression> defaultValues = |
55 <dynamic/*int|String*/, ConstantExpression>{}; | 53 <dynamic /*int|String*/, ConstantExpression>{}; |
56 | 54 |
57 ConstantConstructorComputer(TreeElements elements) | 55 ConstantConstructorComputer(TreeElements elements) : super(elements); |
58 : super(elements); | |
59 | 56 |
60 SemanticDeclarationVisitor get declVisitor => this; | 57 SemanticDeclarationVisitor get declVisitor => this; |
61 | 58 |
62 SemanticSendVisitor get sendVisitor => this; | 59 SemanticSendVisitor get sendVisitor => this; |
63 | 60 |
64 ClassElement get currentClass => currentConstructor.enclosingClass; | 61 ClassElement get currentClass => currentConstructor.enclosingClass; |
65 | 62 |
66 ConstructorElement get currentConstructor => elements.analyzedElement; | 63 ConstructorElement get currentConstructor => elements.analyzedElement; |
67 | 64 |
68 apply(Node node, [_]) => node.accept(this); | 65 apply(Node node, [_]) => node.accept(this); |
69 | 66 |
70 visitNode(Node node) { | 67 visitNode(Node node) { |
71 internalError(node, 'Unhandled node $node: ${node.toDebugString()}'); | 68 internalError(node, 'Unhandled node $node: ${node.toDebugString()}'); |
72 } | 69 } |
73 | 70 |
74 @override | 71 @override |
75 bulkHandleNode(Node node, String template, _) { | 72 bulkHandleNode(Node node, String template, _) { |
76 internalError(node, template.replaceFirst('#' , '$node')); | 73 internalError(node, template.replaceFirst('#', '$node')); |
77 } | 74 } |
78 | 75 |
79 internalError(Node node, String message) { | 76 internalError(Node node, String message) { |
80 throw new UnsupportedError(message); | 77 throw new UnsupportedError(message); |
81 } | 78 } |
82 | 79 |
83 ConstantConstructor visitGenerativeConstructorDeclaration( | 80 ConstantConstructor visitGenerativeConstructorDeclaration( |
84 FunctionExpression node, | 81 FunctionExpression node, |
85 ConstructorElement constructor, | 82 ConstructorElement constructor, |
86 NodeList parameters, | 83 NodeList parameters, |
87 NodeList initializers, | 84 NodeList initializers, |
88 Node body, | 85 Node body, |
89 _) { | 86 _) { |
90 applyParameters(parameters, _); | 87 applyParameters(parameters, _); |
91 ConstructedConstantExpression constructorInvocation = | 88 ConstructedConstantExpression constructorInvocation = |
92 applyInitializers(node, _); | 89 applyInitializers(node, _); |
93 return new GenerativeConstantConstructor( | 90 return new GenerativeConstantConstructor( |
94 currentClass.thisType, defaultValues, fieldMap, constructorInvocation); | 91 currentClass.thisType, defaultValues, fieldMap, constructorInvocation); |
95 } | 92 } |
96 | 93 |
97 ConstantConstructor visitRedirectingGenerativeConstructorDeclaration( | 94 ConstantConstructor visitRedirectingGenerativeConstructorDeclaration( |
98 FunctionExpression node, | 95 FunctionExpression node, |
99 ConstructorElement constructor, | 96 ConstructorElement constructor, |
(...skipping 24 matching lines...) Expand all Loading... |
124 arguments.add(new NamedArgumentReference(name)); | 121 arguments.add(new NamedArgumentReference(name)); |
125 } else { | 122 } else { |
126 arguments.add(new PositionalArgumentReference(index)); | 123 arguments.add(new PositionalArgumentReference(index)); |
127 } | 124 } |
128 index++; | 125 index++; |
129 } | 126 } |
130 CallStructure callStructure = new CallStructure(index, argumentNames); | 127 CallStructure callStructure = new CallStructure(index, argumentNames); |
131 | 128 |
132 return new RedirectingFactoryConstantConstructor( | 129 return new RedirectingFactoryConstantConstructor( |
133 new ConstructedConstantExpression( | 130 new ConstructedConstantExpression( |
134 redirectionType, | 131 redirectionType, redirectionTarget, callStructure, arguments)); |
135 redirectionTarget, | |
136 callStructure, | |
137 arguments)); | |
138 } | 132 } |
139 | 133 |
140 @override | 134 @override |
141 visitFactoryConstructorDeclaration( | 135 visitFactoryConstructorDeclaration(FunctionExpression node, |
142 FunctionExpression node, | 136 ConstructorElement constructor, NodeList parameters, Node body, _) { |
143 ConstructorElement constructor, | |
144 NodeList parameters, | |
145 Node body, _) { | |
146 // TODO(johnniwinther): Handle constant constructors with errors. | 137 // TODO(johnniwinther): Handle constant constructors with errors. |
147 internalError(node, "Factory constructor cannot be constant: $node."); | 138 internalError(node, "Factory constructor cannot be constant: $node."); |
148 } | 139 } |
149 | 140 |
150 applyParameters(NodeList parameters, _) { | 141 applyParameters(NodeList parameters, _) { |
151 computeParameterStructures(parameters).forEach((s) => s.dispatch(this, _)); | 142 computeParameterStructures(parameters).forEach((s) => s.dispatch(this, _)); |
152 } | 143 } |
153 | 144 |
154 visitParameterDeclaration( | 145 visitParameterDeclaration(VariableDefinitions node, Node definition, |
155 VariableDefinitions node, | 146 ParameterElement parameter, int index, _) { |
156 Node definition, | |
157 ParameterElement parameter, | |
158 int index, | |
159 _) { | |
160 // Do nothing. | 147 // Do nothing. |
161 } | 148 } |
162 | 149 |
163 visitOptionalParameterDeclaration( | 150 visitOptionalParameterDeclaration( |
164 VariableDefinitions node, | 151 VariableDefinitions node, |
165 Node definition, | 152 Node definition, |
166 ParameterElement parameter, | 153 ParameterElement parameter, |
167 ConstantExpression defaultValue, | 154 ConstantExpression defaultValue, |
168 int index, | 155 int index, |
169 _) { | 156 _) { |
170 assert(invariant(node, defaultValue != null)); | 157 assert(invariant(node, defaultValue != null)); |
171 defaultValues[index] = defaultValue; | 158 defaultValues[index] = defaultValue; |
172 } | 159 } |
173 | 160 |
174 visitNamedParameterDeclaration( | 161 visitNamedParameterDeclaration(VariableDefinitions node, Node definition, |
175 VariableDefinitions node, | 162 ParameterElement parameter, ConstantExpression defaultValue, _) { |
176 Node definition, | |
177 ParameterElement parameter, | |
178 ConstantExpression defaultValue, | |
179 _) { | |
180 assert(invariant(node, defaultValue != null)); | 163 assert(invariant(node, defaultValue != null)); |
181 String name = parameter.name; | 164 String name = parameter.name; |
182 defaultValues[name] = defaultValue; | 165 defaultValues[name] = defaultValue; |
183 } | 166 } |
184 | 167 |
185 visitInitializingFormalDeclaration( | 168 visitInitializingFormalDeclaration(VariableDefinitions node, Node definition, |
186 VariableDefinitions node, | 169 InitializingFormalElement parameter, int index, _) { |
187 Node definition, | |
188 InitializingFormalElement parameter, | |
189 int index, | |
190 _) { | |
191 fieldMap[parameter.fieldElement] = new PositionalArgumentReference(index); | 170 fieldMap[parameter.fieldElement] = new PositionalArgumentReference(index); |
192 } | 171 } |
193 | 172 |
194 visitOptionalInitializingFormalDeclaration( | 173 visitOptionalInitializingFormalDeclaration( |
195 VariableDefinitions node, | 174 VariableDefinitions node, |
196 Node definition, | 175 Node definition, |
197 InitializingFormalElement parameter, | 176 InitializingFormalElement parameter, |
198 ConstantExpression defaultValue, | 177 ConstantExpression defaultValue, |
199 int index, | 178 int index, |
200 _) { | 179 _) { |
(...skipping 23 matching lines...) Expand all Loading... |
224 for (InitializerStructure structure in initializers.initializers) { | 203 for (InitializerStructure structure in initializers.initializers) { |
225 if (structure.isConstructorInvoke) { | 204 if (structure.isConstructorInvoke) { |
226 constructorInvocation = structure.dispatch(this, _); | 205 constructorInvocation = structure.dispatch(this, _); |
227 } else { | 206 } else { |
228 structure.dispatch(this, _); | 207 structure.dispatch(this, _); |
229 } | 208 } |
230 } | 209 } |
231 return constructorInvocation; | 210 return constructorInvocation; |
232 } | 211 } |
233 | 212 |
234 visitFieldInitializer( | 213 visitFieldInitializer(SendSet node, FieldElement field, Node initializer, _) { |
235 SendSet node, | |
236 FieldElement field, | |
237 Node initializer, | |
238 _) { | |
239 fieldMap[field] = apply(initializer); | 214 fieldMap[field] = apply(initializer); |
240 } | 215 } |
241 | 216 |
242 visitParameterGet( | 217 visitParameterGet(Send node, ParameterElement parameter, _) { |
243 Send node, | |
244 ParameterElement parameter, | |
245 _) { | |
246 if (parameter.isNamed) { | 218 if (parameter.isNamed) { |
247 return new NamedArgumentReference(parameter.name); | 219 return new NamedArgumentReference(parameter.name); |
248 } else { | 220 } else { |
249 return new PositionalArgumentReference( | 221 return new PositionalArgumentReference( |
250 parameter.functionDeclaration.parameters.indexOf(parameter)); | 222 parameter.functionDeclaration.parameters.indexOf(parameter)); |
251 } | 223 } |
252 } | 224 } |
253 | 225 |
254 ConstructedConstantExpression visitSuperConstructorInvoke( | 226 ConstructedConstantExpression visitSuperConstructorInvoke( |
255 Send node, | 227 Send node, |
256 ConstructorElement superConstructor, | 228 ConstructorElement superConstructor, |
257 InterfaceType type, | 229 InterfaceType type, |
258 NodeList arguments, | 230 NodeList arguments, |
259 CallStructure callStructure, | 231 CallStructure callStructure, |
260 _) { | 232 _) { |
261 List<ConstantExpression> argumentExpression = | 233 List<ConstantExpression> argumentExpression = |
262 arguments.nodes.map((a) => apply(a)).toList(); | 234 arguments.nodes.map((a) => apply(a)).toList(); |
263 return new ConstructedConstantExpression( | 235 return new ConstructedConstantExpression( |
264 type, | 236 type, superConstructor, callStructure, argumentExpression); |
265 superConstructor, | |
266 callStructure, | |
267 argumentExpression); | |
268 } | 237 } |
269 | 238 |
270 ConstructedConstantExpression visitImplicitSuperConstructorInvoke( | 239 ConstructedConstantExpression visitImplicitSuperConstructorInvoke( |
271 FunctionExpression node, | 240 FunctionExpression node, |
272 ConstructorElement superConstructor, | 241 ConstructorElement superConstructor, |
273 InterfaceType type, | 242 InterfaceType type, |
274 _) { | 243 _) { |
275 return new ConstructedConstantExpression( | 244 return new ConstructedConstantExpression(type, superConstructor, |
276 type, | 245 CallStructure.NO_ARGS, const <ConstantExpression>[]); |
277 superConstructor, | |
278 CallStructure.NO_ARGS, | |
279 const <ConstantExpression>[]); | |
280 } | 246 } |
281 | 247 |
282 ConstructedConstantExpression visitThisConstructorInvoke( | 248 ConstructedConstantExpression visitThisConstructorInvoke( |
283 Send node, | 249 Send node, |
284 ConstructorElement thisConstructor, | 250 ConstructorElement thisConstructor, |
285 NodeList arguments, | 251 NodeList arguments, |
286 CallStructure callStructure, | 252 CallStructure callStructure, |
287 _) { | 253 _) { |
288 List<ConstantExpression> argumentExpression = | 254 List<ConstantExpression> argumentExpression = |
289 arguments.nodes.map((a) => apply(a)).toList(); | 255 arguments.nodes.map((a) => apply(a)).toList(); |
290 return new ConstructedConstantExpression( | 256 return new ConstructedConstantExpression(currentClass.thisType, |
291 currentClass.thisType, | 257 thisConstructor, callStructure, argumentExpression); |
292 thisConstructor, | |
293 callStructure, | |
294 argumentExpression); | |
295 } | 258 } |
296 | 259 |
297 @override | 260 @override |
298 ConstantExpression visitBinary( | 261 ConstantExpression visitBinary( |
299 Send node, | 262 Send node, Node left, BinaryOperator operator, Node right, _) { |
300 Node left, | 263 return new BinaryConstantExpression(apply(left), operator, apply(right)); |
301 BinaryOperator operator, | |
302 Node right, | |
303 _) { | |
304 return new BinaryConstantExpression( | |
305 apply(left), operator, apply(right)); | |
306 } | 264 } |
307 | 265 |
308 | |
309 @override | 266 @override |
310 ConstantExpression visitUnary( | 267 ConstantExpression visitUnary( |
311 Send node, | 268 Send node, UnaryOperator operator, Node expression, _) { |
312 UnaryOperator operator, | 269 return new UnaryConstantExpression(operator, apply(expression)); |
313 Node expression, | |
314 _) { | |
315 return new UnaryConstantExpression( | |
316 operator, apply(expression)); | |
317 } | 270 } |
318 | 271 |
319 @override | 272 @override |
320 ConstantExpression visitStaticFieldGet( | 273 ConstantExpression visitStaticFieldGet(Send node, FieldElement field, _) { |
321 Send node, | |
322 FieldElement field, | |
323 _) { | |
324 return new VariableConstantExpression(field); | 274 return new VariableConstantExpression(field); |
325 } | 275 } |
326 | 276 |
327 @override | 277 @override |
328 ConstantExpression visitTopLevelFieldGet( | 278 ConstantExpression visitTopLevelFieldGet(Send node, FieldElement field, _) { |
329 Send node, | |
330 FieldElement field, | |
331 _) { | |
332 return new VariableConstantExpression(field); | 279 return new VariableConstantExpression(field); |
333 } | 280 } |
334 | 281 |
335 @override | 282 @override |
336 ConstantExpression visitLiteralInt(LiteralInt node) { | 283 ConstantExpression visitLiteralInt(LiteralInt node) { |
337 return new IntConstantExpression(node.value); | 284 return new IntConstantExpression(node.value); |
338 } | 285 } |
339 | 286 |
340 @override | 287 @override |
341 ConstantExpression visitLiteralBool(LiteralBool node) { | 288 ConstantExpression visitLiteralBool(LiteralBool node) { |
342 return new BoolConstantExpression(node.value); | 289 return new BoolConstantExpression(node.value); |
343 } | 290 } |
344 | 291 |
345 @override | 292 @override |
346 ConstantExpression visitLiteralNull(LiteralNull node) { | 293 ConstantExpression visitLiteralNull(LiteralNull node) { |
347 return new NullConstantExpression(); | 294 return new NullConstantExpression(); |
348 } | 295 } |
349 | 296 |
350 @override | 297 @override |
351 ConstantExpression visitLiteralString(LiteralString node) { | 298 ConstantExpression visitLiteralString(LiteralString node) { |
352 return new StringConstantExpression(node.dartString.slowToString()); | 299 return new StringConstantExpression(node.dartString.slowToString()); |
353 } | 300 } |
354 | 301 |
355 @override | 302 @override |
356 ConstantExpression visitConditional(Conditional node) { | 303 ConstantExpression visitConditional(Conditional node) { |
357 return new ConditionalConstantExpression( | 304 return new ConditionalConstantExpression(apply(node.condition), |
358 apply(node.condition), | 305 apply(node.thenExpression), apply(node.elseExpression)); |
359 apply(node.thenExpression), | |
360 apply(node.elseExpression)); | |
361 } | 306 } |
362 | 307 |
363 @override | 308 @override |
364 ConstantExpression visitParenthesizedExpression(ParenthesizedExpression node)
{ | 309 ConstantExpression visitParenthesizedExpression( |
| 310 ParenthesizedExpression node) { |
365 return apply(node.expression); | 311 return apply(node.expression); |
366 } | 312 } |
367 | 313 |
368 @override | 314 @override |
369 ConstantExpression visitTopLevelFunctionInvoke( | 315 ConstantExpression visitTopLevelFunctionInvoke( |
370 Send node, | 316 Send node, |
371 MethodElement function, | 317 MethodElement function, |
372 NodeList arguments, | 318 NodeList arguments, |
373 CallStructure callStructure, | 319 CallStructure callStructure, |
374 _) { | 320 _) { |
375 if (function.name != 'identical' || !function.library.isDartCore) { | 321 if (function.name != 'identical' || !function.library.isDartCore) { |
376 throw new UnsupportedError("Unexpected function call: $function"); | 322 throw new UnsupportedError("Unexpected function call: $function"); |
377 } | 323 } |
378 return new IdenticalConstantExpression( | 324 return new IdenticalConstantExpression( |
379 apply(arguments.nodes.head), apply(arguments.nodes.tail.head)); | 325 apply(arguments.nodes.head), apply(arguments.nodes.tail.head)); |
380 } | 326 } |
381 | 327 |
382 @override | 328 @override |
383 ConstantExpression visitNamedArgument(NamedArgument node) { | 329 ConstantExpression visitNamedArgument(NamedArgument node) { |
384 return apply(node.expression); | 330 return apply(node.expression); |
385 } | 331 } |
386 } | 332 } |
OLD | NEW |