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

Side by Side Diff: pkg/compiler/lib/src/constants/constructors.dart

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

Powered by Google App Engine
This is Rietveld 408576698