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

Side by Side Diff: pkg/compiler/lib/src/compile_time_constants.dart

Issue 1148343004: Remove ConstantExpression.value (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Update comments. Created 5 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
« no previous file with comments | « no previous file | pkg/compiler/lib/src/compiler.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 library dart2js.compile_time_constant_evaluator; 5 library dart2js.compile_time_constant_evaluator;
6 6
7 import 'constant_system_dart.dart'; 7 import 'constant_system_dart.dart';
8 import 'constants/constant_system.dart'; 8 import 'constants/constant_system.dart';
9 import 'constants/expressions.dart'; 9 import 'constants/expressions.dart';
10 import 'constants/values.dart'; 10 import 'constants/values.dart';
11 import 'dart_types.dart'; 11 import 'dart_types.dart';
12 import 'dart2jslib.dart' show Compiler, CompilerTask, MessageKind, WorldImpact, invariant; 12 import 'dart2jslib.dart' show Compiler, CompilerTask, MessageKind, WorldImpact, invariant;
13 import 'elements/elements.dart'; 13 import 'elements/elements.dart';
14 import 'elements/modelx.dart' show FunctionElementX; 14 import 'elements/modelx.dart' show FunctionElementX;
15 import 'helpers/helpers.dart'; 15 import 'helpers/helpers.dart';
16 import 'resolution/resolution.dart'; 16 import 'resolution/resolution.dart';
17 import 'resolution/operators.dart'; 17 import 'resolution/operators.dart';
18 import 'tree/tree.dart'; 18 import 'tree/tree.dart';
19 import 'util/util.dart' show Link; 19 import 'util/util.dart' show Link;
20 import 'universe/universe.dart' show CallStructure; 20 import 'universe/universe.dart' show CallStructure;
21 21
22 /// A [ConstantEnvironment] provides access for constants compiled for variable 22 /// A [ConstantEnvironment] provides access for constants compiled for variable
23 /// initializers. 23 /// initializers.
24 abstract class ConstantEnvironment { 24 abstract class ConstantEnvironment {
25 /// The [ConstantSystem] used by this environment.
26 ConstantSystem get constantSystem;
27
28 /// Returns the constant value computed for [expression].
29 // TODO(johnniwinther): Support directly evaluation of [expression].
30 ConstantValue getConstantValue(ConstantExpression expression);
31
32 /// Returns the constant value for the initializer of [element].
33 ConstantValue getConstantValueForVariable(VariableElement element);
34
25 /// Returns the constant for the initializer of [element]. 35 /// Returns the constant for the initializer of [element].
26 ConstantExpression getConstantForVariable(VariableElement element); 36 ConstantExpression getConstantForVariable(VariableElement element);
27 } 37 }
28 38
29 /// A class that can compile and provide constants for variables, nodes and 39 /// A class that can compile and provide constants for variables, nodes and
30 /// metadata. 40 /// metadata.
31 abstract class ConstantCompiler extends ConstantEnvironment { 41 abstract class ConstantCompiler extends ConstantEnvironment {
32 /// Compiles the compile-time constant for the initializer of [element], or 42 /// Compiles the compile-time constant for the initializer of [element], or
33 /// reports an error if the initializer is not a compile-time constant. 43 /// reports an error if the initializer is not a compile-time constant.
34 /// 44 ///
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 /// 76 ///
67 /// The returned constant is always of the frontend interpretation. 77 /// The returned constant is always of the frontend interpretation.
68 ConstantExpression compileMetadata(MetadataAnnotation metadata, 78 ConstantExpression compileMetadata(MetadataAnnotation metadata,
69 Node node, 79 Node node,
70 TreeElements elements); 80 TreeElements elements);
71 } 81 }
72 82
73 /// A [BackendConstantEnvironment] provides access to constants needed for 83 /// A [BackendConstantEnvironment] provides access to constants needed for
74 /// backend implementation. 84 /// backend implementation.
75 abstract class BackendConstantEnvironment extends ConstantEnvironment { 85 abstract class BackendConstantEnvironment extends ConstantEnvironment {
86 /// Returns the compile-time constant value associated with [node].
87 ///
88 /// Depending on implementation, the constant might be stored in [elements].
89 ConstantValue getConstantValueForNode(Node node, TreeElements elements);
90
76 /// Returns the compile-time constant associated with [node]. 91 /// Returns the compile-time constant associated with [node].
77 /// 92 ///
78 /// Depending on implementation, the constant might be stored in [elements]. 93 /// Depending on implementation, the constant might be stored in [elements].
79 ConstantExpression getConstantForNode(Node node, TreeElements elements); 94 ConstantExpression getConstantForNode(Node node, TreeElements elements);
80 95
81 /// Returns the compile-time constant value of [metadata]. 96 /// Returns the compile-time constant value of [metadata].
82 ConstantExpression getConstantForMetadata(MetadataAnnotation metadata); 97 ConstantValue getConstantValueForMetadata(MetadataAnnotation metadata);
83 } 98 }
84 99
85 /// Interface for the task that compiles the constant environments for the 100 /// Interface for the task that compiles the constant environments for the
86 /// frontend and backend interpretation of compile-time constants. 101 /// frontend and backend interpretation of compile-time constants.
87 abstract class ConstantCompilerTask extends CompilerTask 102 abstract class ConstantCompilerTask extends CompilerTask
88 implements ConstantCompiler { 103 implements ConstantCompiler {
89 ConstantCompilerTask(Compiler compiler) : super(compiler); 104 ConstantCompilerTask(Compiler compiler) : super(compiler);
105
106 /// Copy all cached constant values from [task].
107 ///
108 /// This is a hack to support reuse cached compilers in memory_compiler.
109 // TODO(johnniwinther): Remove this when values are computed from the
110 // expressions.
111 void copyConstantValues(ConstantCompilerTask task);
90 } 112 }
91 113
92 /** 114 /**
93 * The [ConstantCompilerBase] is provides base implementation for compilation of 115 * The [ConstantCompilerBase] is provides base implementation for compilation of
94 * compile-time constants for both the Dart and JavaScript interpretation of 116 * compile-time constants for both the Dart and JavaScript interpretation of
95 * constants. It keeps track of compile-time constants for initializations of 117 * constants. It keeps track of compile-time constants for initializations of
96 * global and static fields, and default values of optional parameters. 118 * global and static fields, and default values of optional parameters.
97 */ 119 */
98 abstract class ConstantCompilerBase implements ConstantCompiler { 120 abstract class ConstantCompilerBase implements ConstantCompiler {
99 final Compiler compiler; 121 final Compiler compiler;
(...skipping 10 matching lines...) Expand all
110 * May contain default parameter values of optional arguments. 132 * May contain default parameter values of optional arguments.
111 * 133 *
112 * Invariant: The keys in this map are declarations. 134 * Invariant: The keys in this map are declarations.
113 */ 135 */
114 final Map<VariableElement, ConstantExpression> initialVariableValues = 136 final Map<VariableElement, ConstantExpression> initialVariableValues =
115 new Map<VariableElement, ConstantExpression>(); 137 new Map<VariableElement, ConstantExpression>();
116 138
117 /** The set of variable elements that are in the process of being computed. */ 139 /** The set of variable elements that are in the process of being computed. */
118 final Set<VariableElement> pendingVariables = new Set<VariableElement>(); 140 final Set<VariableElement> pendingVariables = new Set<VariableElement>();
119 141
142 final Map<ConstantExpression, ConstantValue> constantValueMap =
143 <ConstantExpression, ConstantValue>{};
144
120 ConstantCompilerBase(this.compiler, this.constantSystem); 145 ConstantCompilerBase(this.compiler, this.constantSystem);
121 146
147 @override
148 ConstantValue getConstantValueForVariable(VariableElement element) {
149 return getConstantValue(initialVariableValues[element.declaration]);
150 }
151
152 @override
122 ConstantExpression getConstantForVariable(VariableElement element) { 153 ConstantExpression getConstantForVariable(VariableElement element) {
123 return initialVariableValues[element.declaration]; 154 return initialVariableValues[element.declaration];
124 } 155 }
125 156
126 ConstantExpression compileConstant(VariableElement element) { 157 ConstantExpression compileConstant(VariableElement element) {
127 return compileVariable(element, isConst: true); 158 return compileVariable(element, isConst: true);
128 } 159 }
129 160
130 ConstantExpression compileVariable(VariableElement element, 161 ConstantExpression compileVariable(VariableElement element,
131 {bool isConst: false}) { 162 {bool isConst: false}) {
(...skipping 20 matching lines...) Expand all
152 * error. 183 * error.
153 */ 184 */
154 ConstantExpression compileVariableWithDefinitions(VariableElement element, 185 ConstantExpression compileVariableWithDefinitions(VariableElement element,
155 TreeElements definitions, 186 TreeElements definitions,
156 {bool isConst: false}) { 187 {bool isConst: false}) {
157 Node node = element.node; 188 Node node = element.node;
158 if (pendingVariables.contains(element)) { 189 if (pendingVariables.contains(element)) {
159 if (isConst) { 190 if (isConst) {
160 compiler.reportError( 191 compiler.reportError(
161 node, MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS); 192 node, MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS);
162 return new ErroneousConstantExpression(); 193 ConstantExpression expression = new ErroneousConstantExpression();
194 constantValueMap[expression] = constantSystem.createNull();
195 return expression;
163 } 196 }
164 return null; 197 return null;
165 } 198 }
166 pendingVariables.add(element); 199 pendingVariables.add(element);
167 200
168 Expression initializer = element.initializer; 201 Expression initializer = element.initializer;
169 ConstantExpression value; 202 ConstantExpression expression;
170 if (initializer == null) { 203 if (initializer == null) {
171 // No initial value. 204 // No initial value.
172 value = new NullConstantExpression(new NullConstantValue()); 205 expression = new NullConstantExpression();
206 constantValueMap[expression] = constantSystem.createNull();
173 } else { 207 } else {
174 value = compileNodeWithDefinitions( 208 expression = compileNodeWithDefinitions(
175 initializer, definitions, isConst: isConst); 209 initializer, definitions, isConst: isConst);
176 if (compiler.enableTypeAssertions && 210 if (compiler.enableTypeAssertions &&
177 value != null && 211 expression != null &&
178 element.isField) { 212 element.isField) {
179 DartType elementType = element.type; 213 DartType elementType = element.type;
180 if (elementType.isMalformed && !value.value.isNull) { 214 ConstantValue value = getConstantValue(expression);
215 if (elementType.isMalformed && !value.isNull) {
181 if (isConst) { 216 if (isConst) {
182 ErroneousElement element = elementType.element; 217 ErroneousElement element = elementType.element;
183 compiler.reportError( 218 compiler.reportError(
184 node, element.messageKind, element.messageArguments); 219 node, element.messageKind, element.messageArguments);
185 } else { 220 } else {
186 // We need to throw an exception at runtime. 221 // We need to throw an exception at runtime.
187 value = null; 222 expression = null;
188 } 223 }
189 } else { 224 } else {
190 DartType constantType = value.value.getType(compiler.coreTypes); 225 DartType constantType = value.getType(compiler.coreTypes);
191 if (!constantSystem.isSubtype(compiler.types, 226 if (!constantSystem.isSubtype(compiler.types,
192 constantType, elementType)) { 227 constantType, elementType)) {
193 if (isConst) { 228 if (isConst) {
194 compiler.reportError( 229 compiler.reportError(
195 node, MessageKind.NOT_ASSIGNABLE, 230 node, MessageKind.NOT_ASSIGNABLE,
196 {'fromType': constantType, 'toType': elementType}); 231 {'fromType': constantType, 'toType': elementType});
197 } else { 232 } else {
198 // If the field cannot be lazily initialized, we will throw 233 // If the field cannot be lazily initialized, we will throw
199 // the exception at runtime. 234 // the exception at runtime.
200 value = null; 235 expression = null;
201 } 236 }
202 } 237 }
203 } 238 }
204 } 239 }
205 } 240 }
206 if (value != null) { 241 if (expression != null) {
207 initialVariableValues[element.declaration] = value; 242 initialVariableValues[element.declaration] = expression;
208 } else { 243 } else {
209 assert(invariant(element, !isConst, 244 assert(invariant(element, !isConst,
210 message: "Variable $element does not compile to a constant.")); 245 message: "Variable $element does not compile to a constant."));
211 } 246 }
212 pendingVariables.remove(element); 247 pendingVariables.remove(element);
213 return value; 248 return expression;
214 } 249 }
215 250
216 ConstantExpression compileNodeWithDefinitions(Node node, 251 ConstantExpression compileNodeWithDefinitions(Node node,
217 TreeElements definitions, 252 TreeElements definitions,
218 {bool isConst: true}) { 253 {bool isConst: true}) {
219 assert(node != null); 254 assert(node != null);
220 CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator( 255 CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator(
221 this, definitions, compiler, isConst: isConst); 256 this, definitions, compiler, isConst: isConst);
222 AstConstant constant = evaluator.evaluate(node); 257 AstConstant constant = evaluator.evaluate(node);
223 return constant != null ? constant.expression : null; 258 if (constant != null) {
259 constantValueMap[constant.expression] = constant.value;
260 return constant.expression;
261 }
262 return null;
263 }
264
265 ConstantValue getConstantValue(ConstantExpression expression) {
266 return constantValueMap[expression];
224 } 267 }
225 268
226 ConstantExpression compileNode(Node node, TreeElements elements, 269 ConstantExpression compileNode(Node node, TreeElements elements,
227 {bool enforceConst: true}) { 270 {bool enforceConst: true}) {
228 return compileNodeWithDefinitions(node, elements, isConst: enforceConst); 271 return compileNodeWithDefinitions(node, elements, isConst: enforceConst);
229 } 272 }
230 273
231 ConstantExpression compileMetadata(MetadataAnnotation metadata, 274 ConstantExpression compileMetadata(MetadataAnnotation metadata,
232 Node node, 275 Node node,
233 TreeElements elements) { 276 TreeElements elements) {
(...skipping 14 matching lines...) Expand all
248 /// [ConstantCompiler] that uses the Dart semantics for the compile-time 291 /// [ConstantCompiler] that uses the Dart semantics for the compile-time
249 /// constant evaluation. 292 /// constant evaluation.
250 class DartConstantCompiler extends ConstantCompilerBase { 293 class DartConstantCompiler extends ConstantCompilerBase {
251 DartConstantCompiler(Compiler compiler) 294 DartConstantCompiler(Compiler compiler)
252 : super(compiler, const DartConstantSystem()); 295 : super(compiler, const DartConstantSystem());
253 296
254 ConstantExpression getConstantForNode(Node node, TreeElements definitions) { 297 ConstantExpression getConstantForNode(Node node, TreeElements definitions) {
255 return definitions.getConstant(node); 298 return definitions.getConstant(node);
256 } 299 }
257 300
258 ConstantExpression getConstantForMetadata(MetadataAnnotation metadata) {
259 return metadata.constant;
260 }
261
262 ConstantExpression compileNodeWithDefinitions(Node node, 301 ConstantExpression compileNodeWithDefinitions(Node node,
263 TreeElements definitions, 302 TreeElements definitions,
264 {bool isConst: true}) { 303 {bool isConst: true}) {
265 ConstantExpression constant = definitions.getConstant(node); 304 ConstantExpression constant = definitions.getConstant(node);
266 if (constant != null) { 305 if (constant != null) {
267 return constant; 306 return constant;
268 } 307 }
269 constant = 308 constant =
270 super.compileNodeWithDefinitions(node, definitions, isConst: isConst); 309 super.compileNodeWithDefinitions(node, definitions, isConst: isConst);
271 if (constant != null) { 310 if (constant != null) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 assert(result != null); 344 assert(result != null);
306 return result; 345 return result;
307 } 346 }
308 347
309 AstConstant visitNode(Node node) { 348 AstConstant visitNode(Node node) {
310 return signalNotCompileTimeConstant(node); 349 return signalNotCompileTimeConstant(node);
311 } 350 }
312 351
313 AstConstant visitLiteralBool(LiteralBool node) { 352 AstConstant visitLiteralBool(LiteralBool node) {
314 return new AstConstant( 353 return new AstConstant(
315 context, node, new BoolConstantExpression( 354 context,
316 node.value, 355 node,
317 constantSystem.createBool(node.value))); 356 new BoolConstantExpression(node.value),
357 constantSystem.createBool(node.value));
318 } 358 }
319 359
320 AstConstant visitLiteralDouble(LiteralDouble node) { 360 AstConstant visitLiteralDouble(LiteralDouble node) {
321 return new AstConstant( 361 return new AstConstant(
322 context, node, new DoubleConstantExpression( 362 context,
323 node.value, 363 node,
324 constantSystem.createDouble(node.value))); 364 new DoubleConstantExpression(node.value),
365 constantSystem.createDouble(node.value));
325 } 366 }
326 367
327 AstConstant visitLiteralInt(LiteralInt node) { 368 AstConstant visitLiteralInt(LiteralInt node) {
328 return new AstConstant( 369 return new AstConstant(
329 context, node, new IntConstantExpression( 370 context,
330 node.value, 371 node,
331 constantSystem.createInt(node.value))); 372 new IntConstantExpression(node.value),
373 constantSystem.createInt(node.value));
332 } 374 }
333 375
334 AstConstant visitLiteralList(LiteralList node) { 376 AstConstant visitLiteralList(LiteralList node) {
335 if (!node.isConst) { 377 if (!node.isConst) {
336 return signalNotCompileTimeConstant(node); 378 return signalNotCompileTimeConstant(node);
337 } 379 }
338 List<ConstantExpression> argumentExpressions = <ConstantExpression>[]; 380 List<ConstantExpression> argumentExpressions = <ConstantExpression>[];
339 List<ConstantValue> argumentValues = <ConstantValue>[]; 381 List<ConstantValue> argumentValues = <ConstantValue>[];
340 for (Link<Node> link = node.elements.nodes; 382 for (Link<Node> link = node.elements.nodes;
341 !link.isEmpty; 383 !link.isEmpty;
342 link = link.tail) { 384 link = link.tail) {
343 AstConstant argument = evaluateConstant(link.head); 385 AstConstant argument = evaluateConstant(link.head);
344 if (argument == null) { 386 if (argument == null) {
345 return null; 387 return null;
346 } 388 }
347 argumentExpressions.add(argument.expression); 389 argumentExpressions.add(argument.expression);
348 argumentValues.add(argument.value); 390 argumentValues.add(argument.value);
349 } 391 }
350 DartType type = elements.getType(node); 392 DartType type = elements.getType(node);
351 return new AstConstant( 393 return new AstConstant(
352 context, node, new ListConstantExpression( 394 context,
353 constantSystem.createList(type, argumentValues), 395 node,
354 type, 396 new ListConstantExpression(type, argumentExpressions),
355 argumentExpressions)); 397 constantSystem.createList(type, argumentValues));
356 } 398 }
357 399
358 AstConstant visitLiteralMap(LiteralMap node) { 400 AstConstant visitLiteralMap(LiteralMap node) {
359 if (!node.isConst) { 401 if (!node.isConst) {
360 return signalNotCompileTimeConstant(node); 402 return signalNotCompileTimeConstant(node);
361 } 403 }
362 List<ConstantExpression> keyExpressions = <ConstantExpression>[]; 404 List<ConstantExpression> keyExpressions = <ConstantExpression>[];
405 List<ConstantExpression> valueExpressions = <ConstantExpression>[];
363 List<ConstantValue> keyValues = <ConstantValue>[]; 406 List<ConstantValue> keyValues = <ConstantValue>[];
364 Map<ConstantValue, ConstantExpression> map = 407 Map<ConstantValue, ConstantValue> map = <ConstantValue, ConstantValue>{};
365 new Map<ConstantValue, ConstantExpression>();
366 for (Link<Node> link = node.entries.nodes; 408 for (Link<Node> link = node.entries.nodes;
367 !link.isEmpty; 409 !link.isEmpty;
368 link = link.tail) { 410 link = link.tail) {
369 LiteralMapEntry entry = link.head; 411 LiteralMapEntry entry = link.head;
370 AstConstant key = evaluateConstant(entry.key); 412 AstConstant key = evaluateConstant(entry.key);
371 if (key == null) { 413 if (key == null) {
372 return null; 414 return null;
373 } 415 }
374 if (!map.containsKey(key.value)) {
375 keyExpressions.add(key.expression);
376 keyValues.add(key.value);
377 } else {
378 compiler.reportWarning(entry.key, MessageKind.EQUAL_MAP_ENTRY_KEY);
379 }
380 AstConstant value = evaluateConstant(entry.value); 416 AstConstant value = evaluateConstant(entry.value);
381 if (value == null) { 417 if (value == null) {
382 return null; 418 return null;
383 } 419 }
384 map[key.value] = value.expression; 420 if (!map.containsKey(key.value)) {
421 keyValues.add(key.value);
422 } else {
423 compiler.reportWarning(entry.key, MessageKind.EQUAL_MAP_ENTRY_KEY);
424 }
425 keyExpressions.add(key.expression);
426 valueExpressions.add(value.expression);
427 map[key.value] = value.value;
385 } 428 }
386 List<ConstantExpression> valueExpressions = map.values.toList();
387 InterfaceType type = elements.getType(node); 429 InterfaceType type = elements.getType(node);
388 return new AstConstant( 430 return new AstConstant(
389 context, node, new MapConstantExpression( 431 context,
390 constantSystem.createMap(compiler, type, keyValues, 432 node,
391 valueExpressions.map((e) => e.value).toList()), 433 new MapConstantExpression(
392 type, 434 type,
393 keyExpressions, 435 keyExpressions,
394 valueExpressions)); 436 valueExpressions),
437 constantSystem.createMap(
438 compiler, type, keyValues, map.values.toList()));
395 } 439 }
396 440
397 AstConstant visitLiteralNull(LiteralNull node) { 441 AstConstant visitLiteralNull(LiteralNull node) {
398 return new AstConstant( 442 return new AstConstant(
399 context, node, new NullConstantExpression( 443 context,
400 constantSystem.createNull())); 444 node,
445 new NullConstantExpression(),
446 constantSystem.createNull());
401 } 447 }
402 448
403 AstConstant visitLiteralString(LiteralString node) { 449 AstConstant visitLiteralString(LiteralString node) {
404 return new AstConstant( 450 return new AstConstant(
405 context, node, new StringConstantExpression( 451 context,
406 node.dartString.slowToString(), 452 node,
407 constantSystem.createString(node.dartString))); 453 new StringConstantExpression(node.dartString.slowToString()),
454 constantSystem.createString(node.dartString));
408 } 455 }
409 456
410 AstConstant visitStringJuxtaposition(StringJuxtaposition node) { 457 AstConstant visitStringJuxtaposition(StringJuxtaposition node) {
411 AstConstant left = evaluate(node.first); 458 AstConstant left = evaluate(node.first);
412 AstConstant right = evaluate(node.second); 459 AstConstant right = evaluate(node.second);
413 if (left == null || right == null) return null; 460 if (left == null || right == null) return null;
414 StringConstantValue leftValue = left.value; 461 StringConstantValue leftValue = left.value;
415 StringConstantValue rightValue = right.value; 462 StringConstantValue rightValue = right.value;
416 return new AstConstant( 463 return new AstConstant(
417 context, node, new ConcatenateConstantExpression( 464 context,
418 constantSystem.createString( 465 node,
419 new DartString.concat( 466 new ConcatenateConstantExpression([left.expression, right.expression]),
420 leftValue.primitiveValue, rightValue.primitiveValue)), 467 constantSystem.createString(
421 [left.expression, right.expression])); 468 new DartString.concat(
469 leftValue.primitiveValue, rightValue.primitiveValue)));
422 } 470 }
423 471
424 AstConstant visitStringInterpolation(StringInterpolation node) { 472 AstConstant visitStringInterpolation(StringInterpolation node) {
425 List<ConstantExpression> subexpressions = <ConstantExpression>[]; 473 List<ConstantExpression> subexpressions = <ConstantExpression>[];
426 AstConstant initialString = evaluate(node.string); 474 AstConstant initialString = evaluate(node.string);
427 if (initialString == null) { 475 if (initialString == null) {
428 return null; 476 return null;
429 } 477 }
430 subexpressions.add(initialString.expression); 478 subexpressions.add(initialString.expression);
431 StringConstantValue initialStringValue = initialString.value; 479 StringConstantValue initialStringValue = initialString.value;
(...skipping 20 matching lines...) Expand all
452 } 500 }
453 accumulator = new DartString.concat(accumulator, expressionString); 501 accumulator = new DartString.concat(accumulator, expressionString);
454 AstConstant partString = evaluate(part.string); 502 AstConstant partString = evaluate(part.string);
455 if (partString == null) return null; 503 if (partString == null) return null;
456 subexpressions.add(partString.expression); 504 subexpressions.add(partString.expression);
457 StringConstantValue partStringValue = partString.value; 505 StringConstantValue partStringValue = partString.value;
458 accumulator = 506 accumulator =
459 new DartString.concat(accumulator, partStringValue.primitiveValue); 507 new DartString.concat(accumulator, partStringValue.primitiveValue);
460 }; 508 };
461 return new AstConstant( 509 return new AstConstant(
462 context, node, new ConcatenateConstantExpression( 510 context,
463 constantSystem.createString(accumulator), 511 node,
464 subexpressions)); 512 new ConcatenateConstantExpression(subexpressions),
513 constantSystem.createString(accumulator));
465 } 514 }
466 515
467 AstConstant visitLiteralSymbol(LiteralSymbol node) { 516 AstConstant visitLiteralSymbol(LiteralSymbol node) {
468 InterfaceType type = compiler.symbolClass.rawType; 517 InterfaceType type = compiler.symbolClass.rawType;
469 String text = node.slowNameString; 518 String text = node.slowNameString;
470 List<AstConstant> arguments = 519 List<AstConstant> arguments =
471 <AstConstant>[new AstConstant(context, node, 520 <AstConstant>[new AstConstant(
472 new StringConstantExpression( 521 context,
473 text, 522 node,
474 constantSystem.createString(new LiteralDartString(text))))]; 523 new StringConstantExpression(text),
524 constantSystem.createString(new LiteralDartString(text)))];
475 ConstructorElement constructor = compiler.symbolConstructor; 525 ConstructorElement constructor = compiler.symbolConstructor;
476 AstConstant constant = createConstructorInvocation( 526 AstConstant constant = createConstructorInvocation(
477 node, type, constructor, CallStructure.ONE_ARG, 527 node, type, constructor, CallStructure.ONE_ARG,
478 normalizedArguments: arguments); 528 normalizedArguments: arguments);
479 return new AstConstant( 529 return new AstConstant(
480 context, node, new SymbolConstantExpression(constant.value, text)); 530 context, node, new SymbolConstantExpression(text), constant.value);
481 } 531 }
482 532
483 ConstantExpression makeTypeConstant(DartType elementType) { 533 ConstantValue makeTypeConstant(DartType elementType) {
484 return new TypeConstantExpression( 534 return constantSystem.createType(compiler, elementType);
485 constantSystem.createType(compiler, elementType), elementType);
486 } 535 }
487 536
488 /// Returns true if the prefix of the send resolves to a deferred import 537 /// Returns true if the prefix of the send resolves to a deferred import
489 /// prefix. 538 /// prefix.
490 bool isDeferredUse(Send send) { 539 bool isDeferredUse(Send send) {
491 if (send == null) return false; 540 if (send == null) return false;
492 return compiler.deferredLoadTask 541 return compiler.deferredLoadTask
493 .deferredPrefixElement(send, elements) != null; 542 .deferredPrefixElement(send, elements) != null;
494 } 543 }
495 544
496 AstConstant visitIdentifier(Identifier node) { 545 AstConstant visitIdentifier(Identifier node) {
497 Element element = elements[node]; 546 Element element = elements[node];
498 if (Elements.isClass(element) || Elements.isTypedef(element)) { 547 if (Elements.isClass(element) || Elements.isTypedef(element)) {
499 TypeDeclarationElement typeDeclarationElement = element; 548 TypeDeclarationElement typeDeclarationElement = element;
500 DartType type = typeDeclarationElement.rawType; 549 DartType type = typeDeclarationElement.rawType;
501 return new AstConstant(element, node, makeTypeConstant(type)); 550 return new AstConstant(element, node,
551 new TypeConstantExpression(type), makeTypeConstant(type));
502 } 552 }
503 return signalNotCompileTimeConstant(node); 553 return signalNotCompileTimeConstant(node);
504 } 554 }
505 555
506 // TODO(floitsch): provide better error-messages. 556 // TODO(floitsch): provide better error-messages.
507 AstConstant visitSend(Send send) { 557 AstConstant visitSend(Send send) {
508 Element element = elements[send]; 558 Element element = elements[send];
509 if (send.isPropertyAccess) { 559 if (send.isPropertyAccess) {
510 ConstantExpression result; 560 AstConstant result;
511
512 if (Elements.isStaticOrTopLevelFunction(element)) { 561 if (Elements.isStaticOrTopLevelFunction(element)) {
513 FunctionElementX function = element; 562 FunctionElementX function = element;
514 function.computeType(compiler); 563 function.computeType(compiler);
515 result = new FunctionConstantExpression( 564 result = new AstConstant(
516 new FunctionConstantValue(function), function); 565 context,
566 send,
567 new FunctionConstantExpression(function),
568 new FunctionConstantValue(function));
517 } else if (Elements.isStaticOrTopLevelField(element)) { 569 } else if (Elements.isStaticOrTopLevelField(element)) {
518 ConstantExpression elementExpression; 570 ConstantExpression elementExpression;
519 if (element.isConst) { 571 if (element.isConst) {
520 elementExpression = handler.compileConstant(element); 572 elementExpression = handler.compileConstant(element);
521 } else if (element.isFinal && !isEvaluatingConstant) { 573 } else if (element.isFinal && !isEvaluatingConstant) {
522 elementExpression = handler.compileVariable(element); 574 elementExpression = handler.compileVariable(element);
523 } 575 }
524 if (elementExpression != null) { 576 if (elementExpression != null) {
525 result = 577 result = new AstConstant(
526 new VariableConstantExpression(elementExpression.value, element); 578 context,
579 send,
580 new VariableConstantExpression(element),
581 handler.getConstantValue(elementExpression));
527 } 582 }
528 } else if (Elements.isClass(element) || Elements.isTypedef(element)) { 583 } else if (Elements.isClass(element) || Elements.isTypedef(element)) {
529 assert(elements.isTypeLiteral(send)); 584 assert(elements.isTypeLiteral(send));
530 result = makeTypeConstant(elements.getTypeLiteralType(send)); 585 DartType elementType = elements.getTypeLiteralType(send);
586 result = new AstConstant(
587 context,
588 send,
589 new TypeConstantExpression(elementType),
590 makeTypeConstant(elementType));
531 } else if (send.receiver != null) { 591 } else if (send.receiver != null) {
532 if (send.selector.asIdentifier().source == "length") { 592 if (send.selector.asIdentifier().source == "length") {
533 AstConstant left = evaluate(send.receiver); 593 AstConstant left = evaluate(send.receiver);
534 if (left != null && left.value.isString) { 594 if (left != null && left.value.isString) {
535 StringConstantValue stringConstantValue = left.value; 595 StringConstantValue stringConstantValue = left.value;
536 DartString string = stringConstantValue.primitiveValue; 596 DartString string = stringConstantValue.primitiveValue;
537 IntConstantValue length = constantSystem.createInt(string.length); 597 IntConstantValue length = constantSystem.createInt(string.length);
538 result = 598 result = new AstConstant(
539 new StringLengthConstantExpression(length, left.expression); 599 context,
600 send,
601 new StringLengthConstantExpression(left.expression),
602 length);
540 } 603 }
541 } 604 }
542 // Fall through to error handling. 605 // Fall through to error handling.
543 } else if (!Elements.isUnresolved(element) 606 } else if (!Elements.isUnresolved(element)
544 && element.isVariable 607 && element.isVariable
545 && element.isConst) { 608 && element.isConst) {
546 ConstantExpression variableExpression = 609 ConstantExpression variableExpression =
547 handler.compileConstant(element); 610 handler.compileConstant(element);
548 if (variableExpression != null) { 611 if (variableExpression != null) {
549 result = new VariableConstantExpression(variableExpression.value, 612 result = new AstConstant(
550 element); 613 context,
614 send,
615 new VariableConstantExpression(element),
616 handler.getConstantValue(variableExpression));
551 } 617 }
552 } 618 }
553 if (result == null) { 619 if (result == null) {
554 return signalNotCompileTimeConstant(send); 620 return signalNotCompileTimeConstant(send);
555 } 621 }
556 if (isDeferredUse(send)) { 622 if (isDeferredUse(send)) {
557 if (isEvaluatingConstant) { 623 if (isEvaluatingConstant) {
558 error(send, MessageKind.DEFERRED_COMPILE_TIME_CONSTANT); 624 error(send, MessageKind.DEFERRED_COMPILE_TIME_CONSTANT);
559 } 625 }
560 PrefixElement prefix = compiler.deferredLoadTask 626 PrefixElement prefix = compiler.deferredLoadTask
561 .deferredPrefixElement(send, elements); 627 .deferredPrefixElement(send, elements);
562 result = new DeferredConstantExpression( 628 result = new AstConstant(
563 new DeferredConstantValue(result.value, prefix), 629 context,
564 result, 630 send,
565 prefix); 631 new DeferredConstantExpression(
632 result.expression,
633 prefix),
634 new DeferredConstantValue(result.value, prefix));
566 compiler.deferredLoadTask 635 compiler.deferredLoadTask
567 .registerConstantDeferredUse(result.value, prefix); 636 .registerConstantDeferredUse(result.value, prefix);
568 } 637 }
569 return new AstConstant(context, send, result); 638 return result;
570 } else if (send.isCall) { 639 } else if (send.isCall) {
571 if (element == compiler.identicalFunction 640 if (element == compiler.identicalFunction
572 && send.argumentCount() == 2) { 641 && send.argumentCount() == 2) {
573 AstConstant left = evaluate(send.argumentsNode.nodes.head); 642 AstConstant left = evaluate(send.argumentsNode.nodes.head);
574 AstConstant right = evaluate(send.argumentsNode.nodes.tail.head); 643 AstConstant right = evaluate(send.argumentsNode.nodes.tail.head);
575 if (left == null || right == null) { 644 if (left == null || right == null) {
576 return null; 645 return null;
577 } 646 }
578 ConstantValue result = 647 ConstantValue result =
579 constantSystem.identity.fold(left.value, right.value); 648 constantSystem.identity.fold(left.value, right.value);
580 if (result != null) { 649 if (result != null) {
581 return new AstConstant( 650 return new AstConstant(
582 context, send, new IdenticalConstantExpression(result, 651 context,
583 left.expression, right.expression)); 652 send,
653 new IdenticalConstantExpression(
654 left.expression, right.expression),
655 result);
584 } 656 }
585 } 657 }
586 return signalNotCompileTimeConstant(send); 658 return signalNotCompileTimeConstant(send);
587 } else if (send.isPrefix) { 659 } else if (send.isPrefix) {
588 assert(send.isOperator); 660 assert(send.isOperator);
589 AstConstant receiverConstant = evaluate(send.receiver); 661 AstConstant receiverConstant = evaluate(send.receiver);
590 if (receiverConstant == null) { 662 if (receiverConstant == null) {
591 return null; 663 return null;
592 } 664 }
593 Operator node = send.selector; 665 Operator node = send.selector;
594 UnaryOperator operator = UnaryOperator.parse(node.source); 666 UnaryOperator operator = UnaryOperator.parse(node.source);
595 UnaryOperation operation = constantSystem.lookupUnary(operator); 667 UnaryOperation operation = constantSystem.lookupUnary(operator);
596 if (operation == null) { 668 if (operation == null) {
597 compiler.internalError(send.selector, "Unexpected operator."); 669 compiler.internalError(send.selector, "Unexpected operator.");
598 } 670 }
599 ConstantValue folded = operation.fold(receiverConstant.value); 671 ConstantValue folded = operation.fold(receiverConstant.value);
600 if (folded == null) { 672 if (folded == null) {
601 return signalNotCompileTimeConstant(send); 673 return signalNotCompileTimeConstant(send);
602 } 674 }
603 return new AstConstant( 675 return new AstConstant(
604 context, send, new UnaryConstantExpression(folded, 676 context,
605 operator, receiverConstant.expression)); 677 send,
678 new UnaryConstantExpression(
679 operator, receiverConstant.expression),
680 folded);
606 } else if (send.isOperator && !send.isPostfix) { 681 } else if (send.isOperator && !send.isPostfix) {
607 assert(send.argumentCount() == 1); 682 assert(send.argumentCount() == 1);
608 AstConstant left = evaluate(send.receiver); 683 AstConstant left = evaluate(send.receiver);
609 AstConstant right = evaluate(send.argumentsNode.nodes.head); 684 AstConstant right = evaluate(send.argumentsNode.nodes.head);
610 if (left == null || right == null) { 685 if (left == null || right == null) {
611 return null; 686 return null;
612 } 687 }
613 ConstantValue leftValue = left.value; 688 ConstantValue leftValue = left.value;
614 ConstantValue rightValue = right.value; 689 ConstantValue rightValue = right.value;
615 Operator node = send.selector.asOperator(); 690 Operator node = send.selector.asOperator();
(...skipping 22 matching lines...) Expand all
638 BinaryOperation operation = constantSystem.lookupBinary(operator); 713 BinaryOperation operation = constantSystem.lookupBinary(operator);
639 if (operation != null) { 714 if (operation != null) {
640 folded = operation.fold(leftValue, rightValue); 715 folded = operation.fold(leftValue, rightValue);
641 } 716 }
642 } 717 }
643 } 718 }
644 if (folded == null) { 719 if (folded == null) {
645 return signalNotCompileTimeConstant(send); 720 return signalNotCompileTimeConstant(send);
646 } 721 }
647 return new AstConstant( 722 return new AstConstant(
648 context, send, new BinaryConstantExpression(folded, 723 context,
649 left.expression, operator, right.expression)); 724 send,
725 new BinaryConstantExpression(
726 left.expression, operator, right.expression),
727 folded);
650 } 728 }
651 return signalNotCompileTimeConstant(send); 729 return signalNotCompileTimeConstant(send);
652 } 730 }
653 731
654 AstConstant visitConditional(Conditional node) { 732 AstConstant visitConditional(Conditional node) {
655 AstConstant condition = evaluate(node.condition); 733 AstConstant condition = evaluate(node.condition);
656 if (condition == null) { 734 if (condition == null) {
657 return null; 735 return null;
658 } else if (!condition.value.isBool) { 736 } else if (!condition.value.isBool) {
659 DartType conditionType = condition.value.getType(compiler.coreTypes); 737 DartType conditionType = condition.value.getType(compiler.coreTypes);
660 if (isEvaluatingConstant) { 738 if (isEvaluatingConstant) {
661 compiler.reportError( 739 compiler.reportError(
662 node.condition, MessageKind.NOT_ASSIGNABLE, 740 node.condition, MessageKind.NOT_ASSIGNABLE,
663 {'fromType': conditionType, 'toType': compiler.boolClass.rawType}); 741 {'fromType': conditionType, 'toType': compiler.boolClass.rawType});
664 return new ErroneousAstConstant(context, node); 742 return new ErroneousAstConstant(context, node);
665 } 743 }
666 return null; 744 return null;
667 } 745 }
668 AstConstant thenExpression = evaluate(node.thenExpression); 746 AstConstant thenExpression = evaluate(node.thenExpression);
669 AstConstant elseExpression = evaluate(node.elseExpression); 747 AstConstant elseExpression = evaluate(node.elseExpression);
670 if (thenExpression == null || elseExpression == null) { 748 if (thenExpression == null || elseExpression == null) {
671 return null; 749 return null;
672 } 750 }
673 BoolConstantValue boolCondition = condition.value; 751 BoolConstantValue boolCondition = condition.value;
674 return new AstConstant( 752 return new AstConstant(
675 context, node, new ConditionalConstantExpression( 753 context,
676 boolCondition.primitiveValue 754 node,
677 ? thenExpression.value 755 new ConditionalConstantExpression(
678 : elseExpression.value,
679 condition.expression, 756 condition.expression,
680 thenExpression.expression, 757 thenExpression.expression,
681 elseExpression.expression)); 758 elseExpression.expression),
759 boolCondition.primitiveValue
760 ? thenExpression.value
761 : elseExpression.value);
682 } 762 }
683 763
684 AstConstant visitSendSet(SendSet node) { 764 AstConstant visitSendSet(SendSet node) {
685 return signalNotCompileTimeConstant(node); 765 return signalNotCompileTimeConstant(node);
686 } 766 }
687 767
688 /** 768 /**
689 * Returns the normalized list of constant arguments that are passed to the 769 * Returns the normalized list of constant arguments that are passed to the
690 * constructor including both the concrete arguments and default values for 770 * constructor including both the concrete arguments and default values for
691 * omitted optional arguments. 771 * omitted optional arguments.
692 * 772 *
693 * Invariant: [target] must be an implementation element. 773 * Invariant: [target] must be an implementation element.
694 */ 774 */
695 List<AstConstant> evaluateArgumentsToConstructor( 775 List<AstConstant> evaluateArgumentsToConstructor(
696 Node node, 776 Node node,
697 CallStructure callStructure, 777 CallStructure callStructure,
698 Link<Node> arguments, 778 Link<Node> arguments,
699 FunctionElement target, 779 FunctionElement target,
700 {AstConstant compileArgument(Node node)}) { 780 {AstConstant compileArgument(Node node)}) {
701 assert(invariant(node, target.isImplementation)); 781 assert(invariant(node, target.isImplementation));
702 782
703 AstConstant compileDefaultValue(VariableElement element) { 783 AstConstant compileDefaultValue(VariableElement element) {
704 ConstantExpression constant = handler.compileConstant(element); 784 ConstantExpression constant = handler.compileConstant(element);
705 return new AstConstant.fromDefaultValue(element, constant); 785 return new AstConstant.fromDefaultValue(
786 element, constant, handler.getConstantValue(constant));
706 } 787 }
707 target.computeSignature(compiler); 788 target.computeSignature(compiler);
708 789
709 if (!callStructure.signatureApplies(target)) { 790 if (!callStructure.signatureApplies(target)) {
710 String name = Elements.constructorNameForDiagnostics( 791 String name = Elements.constructorNameForDiagnostics(
711 target.enclosingClass.name, target.name); 792 target.enclosingClass.name, target.name);
712 compiler.reportError( 793 compiler.reportError(
713 node, 794 node,
714 MessageKind.INVALID_CONSTRUCTOR_ARGUMENTS, 795 MessageKind.INVALID_CONSTRUCTOR_ARGUMENTS,
715 {'constructorName': name}); 796 {'constructorName': name});
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
767 // a post-process action, so we have to make sure it is done here. 848 // a post-process action, so we have to make sure it is done here.
768 compiler.resolver.resolveRedirectionChain(constructor, node); 849 compiler.resolver.resolveRedirectionChain(constructor, node);
769 InterfaceType constructedType = 850 InterfaceType constructedType =
770 constructor.computeEffectiveTargetType(type); 851 constructor.computeEffectiveTargetType(type);
771 ConstructorElement target = constructor.effectiveTarget; 852 ConstructorElement target = constructor.effectiveTarget;
772 // The constructor must be an implementation to ensure that field 853 // The constructor must be an implementation to ensure that field
773 // initializers are handled correctly. 854 // initializers are handled correctly.
774 ConstructorElement implementation = target.implementation; 855 ConstructorElement implementation = target.implementation;
775 856
776 if (implementation.isErroneous) { 857 if (implementation.isErroneous) {
858 // TODO(johnniwinther): This should probably be an [ErroneousAstConstant].
777 return new AstConstant( 859 return new AstConstant(
778 context, node, new ConstructedConstantExpression( 860 context,
779 new ConstructedConstantValue( 861 node,
780 constructedType, const <FieldElement, ConstantValue>{}), 862 new ConstructedConstantExpression(
781 type, 863 type,
782 constructor, 864 constructor,
783 callStructure, 865 callStructure,
784 const <ConstantExpression>[])); 866 const <ConstantExpression>[]),
867 new ConstructedConstantValue(
868 constructedType, const <FieldElement, ConstantValue>{}));
785 } 869 }
786 870
787 List<AstConstant> concreteArguments; 871 List<AstConstant> concreteArguments;
788 if (arguments != null) { 872 if (arguments != null) {
789 Map<Node, AstConstant> concreteArgumentMap = 873 Map<Node, AstConstant> concreteArgumentMap =
790 <Node, AstConstant>{}; 874 <Node, AstConstant>{};
791 for (Link<Node> link = arguments; !link.isEmpty; link = link.tail) { 875 for (Link<Node> link = arguments; !link.isEmpty; link = link.tail) {
792 Node argument = link.head; 876 Node argument = link.head;
793 NamedArgument namedArgument = argument.asNamedArgument(); 877 NamedArgument namedArgument = argument.asNamedArgument();
794 if (namedArgument != null) { 878 if (namedArgument != null) {
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
881 AstConstant createEvaluatedConstant(ConstantValue value) { 965 AstConstant createEvaluatedConstant(ConstantValue value) {
882 966
883 ConstantExpression expression; 967 ConstantExpression expression;
884 ConstantExpression name = concreteArguments[0].expression; 968 ConstantExpression name = concreteArguments[0].expression;
885 ConstantExpression defaultValue; 969 ConstantExpression defaultValue;
886 if (concreteArguments.length > 1) { 970 if (concreteArguments.length > 1) {
887 defaultValue = concreteArguments[1].expression; 971 defaultValue = concreteArguments[1].expression;
888 } 972 }
889 if (constructor == compiler.intEnvironment) { 973 if (constructor == compiler.intEnvironment) {
890 expression = new IntFromEnvironmentConstantExpression( 974 expression = new IntFromEnvironmentConstantExpression(
891 value, name, defaultValue); 975 name, defaultValue);
892 } else if (constructor == compiler.boolEnvironment) { 976 } else if (constructor == compiler.boolEnvironment) {
893 expression = new BoolFromEnvironmentConstantExpression( 977 expression = new BoolFromEnvironmentConstantExpression(
894 value, name, defaultValue); 978 name, defaultValue);
895 } else if (constructor == compiler.stringEnvironment) { 979 } else if (constructor == compiler.stringEnvironment) {
896 expression = new StringFromEnvironmentConstantExpression( 980 expression = new StringFromEnvironmentConstantExpression(
897 value, name, defaultValue); 981 name, defaultValue);
898 } 982 }
899 return new AstConstant(context, node, expression); 983 return new AstConstant(context, node, expression, value);
900 } 984 }
901 985
902 if (value == null) { 986 if (value == null) {
903 return createEvaluatedConstant(defaultValue); 987 return createEvaluatedConstant(defaultValue);
904 } else if (constructor == compiler.intEnvironment) { 988 } else if (constructor == compiler.intEnvironment) {
905 int number = int.parse(value, onError: (_) => null); 989 int number = int.parse(value, onError: (_) => null);
906 return createEvaluatedConstant( 990 return createEvaluatedConstant(
907 (number == null) 991 (number == null)
908 ? defaultValue 992 ? defaultValue
909 : constantSystem.createInt(number)); 993 : constantSystem.createInt(number));
(...skipping 22 matching lines...) Expand all
932 InterfaceType constructedType, 1016 InterfaceType constructedType,
933 ConstructorElement target, 1017 ConstructorElement target,
934 CallStructure callStructure, 1018 CallStructure callStructure,
935 List<AstConstant> concreteArguments, 1019 List<AstConstant> concreteArguments,
936 List<AstConstant> normalizedArguments) { 1020 List<AstConstant> normalizedArguments) {
937 if (target.isRedirectingFactory) { 1021 if (target.isRedirectingFactory) {
938 // This happens is case of cyclic redirection. 1022 // This happens is case of cyclic redirection.
939 assert(invariant(node, compiler.compilationFailed, 1023 assert(invariant(node, compiler.compilationFailed,
940 message: "makeConstructedConstant can only be called with the " 1024 message: "makeConstructedConstant can only be called with the "
941 "effective target: $constructor")); 1025 "effective target: $constructor"));
942 return new AstConstant( 1026 return new ErroneousAstConstant(context, node);
943 context, node, new ErroneousConstantExpression());
944 } 1027 }
945 assert(invariant(node, callStructure.signatureApplies(constructor) || 1028 assert(invariant(node, callStructure.signatureApplies(constructor) ||
946 compiler.compilationFailed, 1029 compiler.compilationFailed,
947 message: "Call structure $callStructure does not apply to constructor " 1030 message: "Call structure $callStructure does not apply to constructor "
948 "$constructor.")); 1031 "$constructor."));
949 1032
950 ConstructorEvaluator evaluator = new ConstructorEvaluator( 1033 ConstructorEvaluator evaluator = new ConstructorEvaluator(
951 constructedType, target, handler, compiler); 1034 constructedType, target, handler, compiler);
952 evaluator.evaluateConstructorFieldValues(normalizedArguments); 1035 evaluator.evaluateConstructorFieldValues(normalizedArguments);
953 Map<FieldElement, AstConstant> fieldConstants = 1036 Map<FieldElement, AstConstant> fieldConstants =
954 evaluator.buildFieldConstants(target.enclosingClass); 1037 evaluator.buildFieldConstants(target.enclosingClass);
955 Map<FieldElement, ConstantValue> fieldValues = 1038 Map<FieldElement, ConstantValue> fieldValues =
956 <FieldElement, ConstantValue>{}; 1039 <FieldElement, ConstantValue>{};
957 fieldConstants.forEach((FieldElement field, AstConstant astConstant) { 1040 fieldConstants.forEach((FieldElement field, AstConstant astConstant) {
958 fieldValues[field] = astConstant.value; 1041 fieldValues[field] = astConstant.value;
959 }); 1042 });
960 return new AstConstant( 1043 return new AstConstant(
961 context, node, new ConstructedConstantExpression( 1044 context,
962 new ConstructedConstantValue(constructedType, fieldValues), 1045 node,
1046 new ConstructedConstantExpression(
963 type, 1047 type,
964 constructor, 1048 constructor,
965 callStructure, 1049 callStructure,
966 concreteArguments.map((e) => e.expression).toList())); 1050 concreteArguments.map((e) => e.expression).toList()),
1051 new ConstructedConstantValue(constructedType, fieldValues));
967 } 1052 }
968 1053
969 AstConstant visitParenthesizedExpression(ParenthesizedExpression node) { 1054 AstConstant visitParenthesizedExpression(ParenthesizedExpression node) {
970 return node.expression.accept(this); 1055 return node.expression.accept(this);
971 } 1056 }
972 1057
973 error(Node node, MessageKind message) { 1058 error(Node node, MessageKind message) {
974 // TODO(floitsch): get the list of constants that are currently compiled 1059 // TODO(floitsch): get the list of constants that are currently compiled
975 // and present some kind of stack-trace. 1060 // and present some kind of stack-trace.
976 compiler.reportError(node, message); 1061 compiler.reportError(node, message);
977 } 1062 }
978 1063
979 AstConstant signalNotCompileTimeConstant(Node node, 1064 AstConstant signalNotCompileTimeConstant(Node node,
980 {MessageKind message: MessageKind.NOT_A_COMPILE_TIME_CONSTANT}) { 1065 {MessageKind message: MessageKind.NOT_A_COMPILE_TIME_CONSTANT}) {
981 if (isEvaluatingConstant) { 1066 if (isEvaluatingConstant) {
982 error(node, message); 1067 error(node, message);
983 1068
984 return new AstConstant( 1069 return new AstConstant(
985 null, node, new ErroneousConstantExpression()); 1070 context,
1071 node,
1072 new ErroneousConstantExpression(),
1073 new NullConstantValue());
986 } 1074 }
987 // Else we don't need to do anything. The final handler is only 1075 // Else we don't need to do anything. The final handler is only
988 // optimistically trying to compile constants. So it is normal that we 1076 // optimistically trying to compile constants. So it is normal that we
989 // sometimes see non-compile time constants. 1077 // sometimes see non-compile time constants.
990 // Simply return [:null:] which is used to propagate a failing 1078 // Simply return [:null:] which is used to propagate a failing
991 // compile-time compilation. 1079 // compile-time compilation.
992 return null; 1080 return null;
993 } 1081 }
994 } 1082 }
995 1083
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
1181 /// inheritance chain of [classElement]. 1269 /// inheritance chain of [classElement].
1182 Map<FieldElement, AstConstant> buildFieldConstants( 1270 Map<FieldElement, AstConstant> buildFieldConstants(
1183 ClassElement classElement) { 1271 ClassElement classElement) {
1184 Map<FieldElement, AstConstant> fieldConstants = 1272 Map<FieldElement, AstConstant> fieldConstants =
1185 <FieldElement, AstConstant>{}; 1273 <FieldElement, AstConstant>{};
1186 classElement.implementation.forEachInstanceField( 1274 classElement.implementation.forEachInstanceField(
1187 (ClassElement enclosing, FieldElement field) { 1275 (ClassElement enclosing, FieldElement field) {
1188 AstConstant fieldValue = fieldValues[field]; 1276 AstConstant fieldValue = fieldValues[field];
1189 if (fieldValue == null) { 1277 if (fieldValue == null) {
1190 // Use the default value. 1278 // Use the default value.
1279 ConstantExpression fieldExpression = handler.compileConstant(field);
1191 fieldValue = new AstConstant.fromDefaultValue( 1280 fieldValue = new AstConstant.fromDefaultValue(
1192 field, handler.compileConstant(field)); 1281 field,
1282 fieldExpression,
1283 handler.getConstantValue(fieldExpression));
1193 } 1284 }
1194 fieldConstants[field] = fieldValue; 1285 fieldConstants[field] = fieldValue;
1195 }, 1286 },
1196 includeSuperAndInjectedMembers: true); 1287 includeSuperAndInjectedMembers: true);
1197 return fieldConstants; 1288 return fieldConstants;
1198 } 1289 }
1199 } 1290 }
1200 1291
1201 /// A constant created from the front-end AST. 1292 /// A constant created from the front-end AST.
1202 /// 1293 ///
1203 /// [element] and [node] point to the source location of the constant. 1294 /// [element] and [node] point to the source location of the constant.
1204 /// [expression] holds the symbolic constant expression and [value] its constant 1295 /// [expression] holds the symbolic constant expression and [value] its constant
1205 /// value. 1296 /// value.
1206 /// 1297 ///
1207 /// This class differs from [ConstantExpression] in that it is coupled to the 1298 /// This class differs from [ConstantExpression] in that it is coupled to the
1208 /// front-end AST whereas [ConstantExpression] is only coupled to the element 1299 /// front-end AST whereas [ConstantExpression] is only coupled to the element
1209 /// model. 1300 /// model.
1210 class AstConstant { 1301 class AstConstant {
1211 final Element element; 1302 final Element element;
1212 final Node node; 1303 final Node node;
1213 final ConstantExpression expression; 1304 final ConstantExpression expression;
1305 final ConstantValue value;
1214 1306
1215 AstConstant(this.element, this.node, this.expression); 1307 AstConstant(this.element, this.node, this.expression, this.value);
1216 1308
1217 factory AstConstant.fromDefaultValue( 1309 factory AstConstant.fromDefaultValue(
1218 VariableElement element, 1310 VariableElement element,
1219 ConstantExpression constant) { 1311 ConstantExpression constant,
1312 ConstantValue value) {
1220 return new AstConstant( 1313 return new AstConstant(
1221 element, 1314 element,
1222 element.initializer != null ? element.initializer : element.node, 1315 element.initializer != null ? element.initializer : element.node,
1223 constant); 1316 constant,
1317 value);
1224 } 1318 }
1225 1319
1226 ConstantValue get value => expression.value;
1227
1228 String toString() => expression.toString(); 1320 String toString() => expression.toString();
1229 } 1321 }
1230 1322
1231 /// A synthetic constant used to recover from errors. 1323 /// A synthetic constant used to recover from errors.
1232 class ErroneousAstConstant extends AstConstant { 1324 class ErroneousAstConstant extends AstConstant {
1233 ErroneousAstConstant(Element element, Node node) 1325 ErroneousAstConstant(Element element, Node node)
1234 : super(element, node, new ErroneousConstantExpression()); 1326 : super(element, node,
1327 // TODO(johnniwinther): Return a [NonConstantValue] instead.
1328 new ErroneousConstantExpression(), new NullConstantValue());
1235 } 1329 }
1236 1330
1237 // TODO(johnniwinther): Avoid the need for this hack. 1331 // TODO(johnniwinther): Avoid the need for this hack.
1238 TreeElements _analyzeElementEagerly(Compiler compiler, AstElement element) { 1332 TreeElements _analyzeElementEagerly(Compiler compiler, AstElement element) {
1239 WorldImpact worldImpact = compiler.analyzeElement(element.declaration); 1333 WorldImpact worldImpact = compiler.analyzeElement(element.declaration);
1240 compiler.enqueuer.resolution.applyImpact(element.declaration, worldImpact); 1334 compiler.enqueuer.resolution.applyImpact(element.declaration, worldImpact);
1241 return element.resolvedAst.elements; 1335 return element.resolvedAst.elements;
1242 } 1336 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/compiler.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698