OLD | NEW |
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 'common.dart'; | 7 import 'common.dart'; |
8 import 'common/resolution.dart' show | 8 import 'common/resolution.dart' show Resolution; |
9 Resolution; | 9 import 'common/tasks.dart' show CompilerTask; |
10 import 'common/tasks.dart' show | 10 import 'compiler.dart' show Compiler; |
11 CompilerTask; | |
12 import 'compiler.dart' show | |
13 Compiler; | |
14 import 'constant_system_dart.dart'; | 11 import 'constant_system_dart.dart'; |
15 import 'constants/constant_system.dart'; | 12 import 'constants/constant_system.dart'; |
16 import 'constants/evaluation.dart'; | 13 import 'constants/evaluation.dart'; |
17 import 'constants/expressions.dart'; | 14 import 'constants/expressions.dart'; |
18 import 'constants/values.dart'; | 15 import 'constants/values.dart'; |
19 import 'core_types.dart' show | 16 import 'core_types.dart' show CoreTypes; |
20 CoreTypes; | |
21 import 'dart_types.dart'; | 17 import 'dart_types.dart'; |
22 import 'elements/elements.dart'; | 18 import 'elements/elements.dart'; |
23 import 'elements/modelx.dart' show | 19 import 'elements/modelx.dart' show FunctionElementX; |
24 FunctionElementX; | 20 import 'resolution/tree_elements.dart' show TreeElements; |
25 import 'resolution/tree_elements.dart' show | |
26 TreeElements; | |
27 import 'resolution/operators.dart'; | 21 import 'resolution/operators.dart'; |
28 import 'tree/tree.dart'; | 22 import 'tree/tree.dart'; |
29 import 'util/util.dart' show | 23 import 'util/util.dart' show Link; |
30 Link; | 24 import 'universe/call_structure.dart' show CallStructure; |
31 import 'universe/call_structure.dart' show | |
32 CallStructure; | |
33 | 25 |
34 /// A [ConstantEnvironment] provides access for constants compiled for variable | 26 /// A [ConstantEnvironment] provides access for constants compiled for variable |
35 /// initializers. | 27 /// initializers. |
36 abstract class ConstantEnvironment { | 28 abstract class ConstantEnvironment { |
37 /// The [ConstantSystem] used by this environment. | 29 /// The [ConstantSystem] used by this environment. |
38 ConstantSystem get constantSystem; | 30 ConstantSystem get constantSystem; |
39 | 31 |
40 /// Returns the constant value computed for [expression]. | 32 /// Returns the constant value computed for [expression]. |
41 // TODO(johnniwinther): Support directly evaluation of [expression]. | 33 // TODO(johnniwinther): Support directly evaluation of [expression]. |
42 ConstantValue getConstantValue(ConstantExpression expression); | 34 ConstantValue getConstantValue(ConstantExpression expression); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 ConstantExpression compileNode(Node node, TreeElements elements, | 72 ConstantExpression compileNode(Node node, TreeElements elements, |
81 {bool enforceConst: true}); | 73 {bool enforceConst: true}); |
82 | 74 |
83 /// Compiles the compile-time constant for the value [metadata], or reports an | 75 /// Compiles the compile-time constant for the value [metadata], or reports an |
84 /// error if the value is not a compile-time constant. | 76 /// error if the value is not a compile-time constant. |
85 /// | 77 /// |
86 /// Depending on implementation, the constant compiler might also compute | 78 /// Depending on implementation, the constant compiler might also compute |
87 /// the compile-time constant for the backend interpretation of constants. | 79 /// the compile-time constant for the backend interpretation of constants. |
88 /// | 80 /// |
89 /// The returned constant is always of the frontend interpretation. | 81 /// The returned constant is always of the frontend interpretation. |
90 ConstantExpression compileMetadata(MetadataAnnotation metadata, | 82 ConstantExpression compileMetadata( |
91 Node node, | 83 MetadataAnnotation metadata, Node node, TreeElements elements); |
92 TreeElements elements); | |
93 | 84 |
94 /// Evaluates [constant] and caches the result. | 85 /// Evaluates [constant] and caches the result. |
95 // TODO(johnniwinther): Remove when all constants are evaluated. | 86 // TODO(johnniwinther): Remove when all constants are evaluated. |
96 void evaluate(ConstantExpression constant); | 87 void evaluate(ConstantExpression constant); |
97 } | 88 } |
98 | 89 |
99 /// A [BackendConstantEnvironment] provides access to constants needed for | 90 /// A [BackendConstantEnvironment] provides access to constants needed for |
100 /// backend implementation. | 91 /// backend implementation. |
101 abstract class BackendConstantEnvironment extends ConstantEnvironment { | 92 abstract class BackendConstantEnvironment extends ConstantEnvironment { |
102 /// Returns the compile-time constant value associated with [node]. | 93 /// Returns the compile-time constant value associated with [node]. |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 } | 166 } |
176 | 167 |
177 ConstantExpression compileConstant(VariableElement element) { | 168 ConstantExpression compileConstant(VariableElement element) { |
178 return internalCompileVariable(element, true, true); | 169 return internalCompileVariable(element, true, true); |
179 } | 170 } |
180 | 171 |
181 @override | 172 @override |
182 void evaluate(ConstantExpression constant) { | 173 void evaluate(ConstantExpression constant) { |
183 constantValueMap.putIfAbsent(constant, () { | 174 constantValueMap.putIfAbsent(constant, () { |
184 return constant.evaluate( | 175 return constant.evaluate( |
185 new _CompilerEnvironment(compiler), | 176 new _CompilerEnvironment(compiler), constantSystem); |
186 constantSystem); | |
187 }); | 177 }); |
188 } | 178 } |
189 | 179 |
190 ConstantExpression compileVariable(VariableElement element) { | 180 ConstantExpression compileVariable(VariableElement element) { |
191 return internalCompileVariable(element, false, true); | 181 return internalCompileVariable(element, false, true); |
192 } | 182 } |
193 | 183 |
194 /// Compile [element] into a constant expression. If [isConst] is true, | 184 /// Compile [element] into a constant expression. If [isConst] is true, |
195 /// then [element] is a constant variable. If [checkType] is true, then | 185 /// then [element] is a constant variable. If [checkType] is true, then |
196 /// report an error if [element] does not typecheck. | 186 /// report an error if [element] does not typecheck. |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
256 node, element.messageKind, element.messageArguments); | 246 node, element.messageKind, element.messageArguments); |
257 } else { | 247 } else { |
258 // We need to throw an exception at runtime. | 248 // We need to throw an exception at runtime. |
259 expression = null; | 249 expression = null; |
260 } | 250 } |
261 } else { | 251 } else { |
262 DartType constantType = value.getType(coreTypes); | 252 DartType constantType = value.getType(coreTypes); |
263 if (!constantSystem.isSubtype( | 253 if (!constantSystem.isSubtype( |
264 compiler.types, constantType, elementType)) { | 254 compiler.types, constantType, elementType)) { |
265 if (isConst) { | 255 if (isConst) { |
266 reporter.reportErrorMessage( | 256 reporter.reportErrorMessage(node, MessageKind.NOT_ASSIGNABLE, |
267 node, | 257 {'fromType': constantType, 'toType': elementType}); |
268 MessageKind.NOT_ASSIGNABLE, | |
269 {'fromType': constantType, | |
270 'toType': elementType}); | |
271 } else { | 258 } else { |
272 // If the field cannot be lazily initialized, we will throw | 259 // If the field cannot be lazily initialized, we will throw |
273 // the exception at runtime. | 260 // the exception at runtime. |
274 expression = null; | 261 expression = null; |
275 } | 262 } |
276 } | 263 } |
277 } | 264 } |
278 } | 265 } |
279 } | 266 } |
280 if (expression != null) { | 267 if (expression != null) { |
281 initialVariableValues[element.declaration] = expression; | 268 initialVariableValues[element.declaration] = expression; |
282 } else { | 269 } else { |
283 assert(invariant(element, !isConst, | 270 assert(invariant(element, !isConst, |
284 message: "Variable $element does not compile to a constant.")); | 271 message: "Variable $element does not compile to a constant.")); |
285 } | 272 } |
286 pendingVariables.remove(element); | 273 pendingVariables.remove(element); |
287 return expression; | 274 return expression; |
288 } | 275 } |
289 | 276 |
290 void cacheConstantValue(ConstantExpression expression, ConstantValue value) { | 277 void cacheConstantValue(ConstantExpression expression, ConstantValue value) { |
291 constantValueMap[expression] = value; | 278 constantValueMap[expression] = value; |
292 } | 279 } |
293 | 280 |
294 ConstantExpression compileNodeWithDefinitions( | 281 ConstantExpression compileNodeWithDefinitions( |
295 Node node, TreeElements definitions, {bool isConst: true}) { | 282 Node node, TreeElements definitions, |
| 283 {bool isConst: true}) { |
296 assert(node != null); | 284 assert(node != null); |
297 CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator( | 285 CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator( |
298 this, definitions, compiler, isConst: isConst); | 286 this, definitions, compiler, |
| 287 isConst: isConst); |
299 AstConstant constant = evaluator.evaluate(node); | 288 AstConstant constant = evaluator.evaluate(node); |
300 if (constant != null) { | 289 if (constant != null) { |
301 cacheConstantValue(constant.expression, constant.value); | 290 cacheConstantValue(constant.expression, constant.value); |
302 return constant.expression; | 291 return constant.expression; |
303 } | 292 } |
304 return null; | 293 return null; |
305 } | 294 } |
306 | 295 |
307 ConstantValue getConstantValue(ConstantExpression expression) { | 296 ConstantValue getConstantValue(ConstantExpression expression) { |
308 return constantValueMap[expression]; | 297 return constantValueMap[expression]; |
(...skipping 24 matching lines...) Expand all Loading... |
333 /// constant evaluation. | 322 /// constant evaluation. |
334 class DartConstantCompiler extends ConstantCompilerBase { | 323 class DartConstantCompiler extends ConstantCompilerBase { |
335 DartConstantCompiler(Compiler compiler) | 324 DartConstantCompiler(Compiler compiler) |
336 : super(compiler, const DartConstantSystem()); | 325 : super(compiler, const DartConstantSystem()); |
337 | 326 |
338 ConstantExpression getConstantForNode(Node node, TreeElements definitions) { | 327 ConstantExpression getConstantForNode(Node node, TreeElements definitions) { |
339 return definitions.getConstant(node); | 328 return definitions.getConstant(node); |
340 } | 329 } |
341 | 330 |
342 ConstantExpression compileNodeWithDefinitions( | 331 ConstantExpression compileNodeWithDefinitions( |
343 Node node, TreeElements definitions, {bool isConst: true}) { | 332 Node node, TreeElements definitions, |
| 333 {bool isConst: true}) { |
344 ConstantExpression constant = definitions.getConstant(node); | 334 ConstantExpression constant = definitions.getConstant(node); |
345 if (constant != null && getConstantValue(constant) != null) { | 335 if (constant != null && getConstantValue(constant) != null) { |
346 return constant; | 336 return constant; |
347 } | 337 } |
348 constant = | 338 constant = |
349 super.compileNodeWithDefinitions(node, definitions, isConst: isConst); | 339 super.compileNodeWithDefinitions(node, definitions, isConst: isConst); |
350 if (constant != null) { | 340 if (constant != null) { |
351 definitions.setConstant(node, constant); | 341 definitions.setConstant(node, constant); |
352 } | 342 } |
353 return constant; | 343 return constant; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
386 isEvaluatingConstant = oldIsEvaluatingConstant; | 376 isEvaluatingConstant = oldIsEvaluatingConstant; |
387 assert(result != null); | 377 assert(result != null); |
388 return result; | 378 return result; |
389 } | 379 } |
390 | 380 |
391 AstConstant visitNode(Node node) { | 381 AstConstant visitNode(Node node) { |
392 return signalNotCompileTimeConstant(node); | 382 return signalNotCompileTimeConstant(node); |
393 } | 383 } |
394 | 384 |
395 AstConstant visitLiteralBool(LiteralBool node) { | 385 AstConstant visitLiteralBool(LiteralBool node) { |
396 return new AstConstant(context, node, | 386 return new AstConstant( |
| 387 context, |
| 388 node, |
397 new BoolConstantExpression(node.value), | 389 new BoolConstantExpression(node.value), |
398 constantSystem.createBool(node.value)); | 390 constantSystem.createBool(node.value)); |
399 } | 391 } |
400 | 392 |
401 AstConstant visitLiteralDouble(LiteralDouble node) { | 393 AstConstant visitLiteralDouble(LiteralDouble node) { |
402 return new AstConstant(context, node, | 394 return new AstConstant( |
| 395 context, |
| 396 node, |
403 new DoubleConstantExpression(node.value), | 397 new DoubleConstantExpression(node.value), |
404 constantSystem.createDouble(node.value)); | 398 constantSystem.createDouble(node.value)); |
405 } | 399 } |
406 | 400 |
407 AstConstant visitLiteralInt(LiteralInt node) { | 401 AstConstant visitLiteralInt(LiteralInt node) { |
408 return new AstConstant(context, node, new IntConstantExpression(node.value), | 402 return new AstConstant(context, node, new IntConstantExpression(node.value), |
409 constantSystem.createInt(node.value)); | 403 constantSystem.createInt(node.value)); |
410 } | 404 } |
411 | 405 |
412 AstConstant visitLiteralList(LiteralList node) { | 406 AstConstant visitLiteralList(LiteralList node) { |
413 if (!node.isConst) { | 407 if (!node.isConst) { |
414 return signalNotCompileTimeConstant(node); | 408 return signalNotCompileTimeConstant(node); |
415 } | 409 } |
416 List<ConstantExpression> argumentExpressions = <ConstantExpression>[]; | 410 List<ConstantExpression> argumentExpressions = <ConstantExpression>[]; |
417 List<ConstantValue> argumentValues = <ConstantValue>[]; | 411 List<ConstantValue> argumentValues = <ConstantValue>[]; |
418 for (Link<Node> link = node.elements.nodes; | 412 for (Link<Node> link = node.elements.nodes; |
419 !link.isEmpty; | 413 !link.isEmpty; |
420 link = link.tail) { | 414 link = link.tail) { |
421 AstConstant argument = evaluateConstant(link.head); | 415 AstConstant argument = evaluateConstant(link.head); |
422 if (argument == null) { | 416 if (argument == null) { |
423 return null; | 417 return null; |
424 } | 418 } |
425 argumentExpressions.add(argument.expression); | 419 argumentExpressions.add(argument.expression); |
426 argumentValues.add(argument.value); | 420 argumentValues.add(argument.value); |
427 } | 421 } |
428 DartType type = elements.getType(node); | 422 DartType type = elements.getType(node); |
429 return new AstConstant(context, node, | 423 return new AstConstant( |
| 424 context, |
| 425 node, |
430 new ListConstantExpression(type, argumentExpressions), | 426 new ListConstantExpression(type, argumentExpressions), |
431 constantSystem.createList(type, argumentValues)); | 427 constantSystem.createList(type, argumentValues)); |
432 } | 428 } |
433 | 429 |
434 AstConstant visitLiteralMap(LiteralMap node) { | 430 AstConstant visitLiteralMap(LiteralMap node) { |
435 if (!node.isConst) { | 431 if (!node.isConst) { |
436 return signalNotCompileTimeConstant(node); | 432 return signalNotCompileTimeConstant(node); |
437 } | 433 } |
438 List<ConstantExpression> keyExpressions = <ConstantExpression>[]; | 434 List<ConstantExpression> keyExpressions = <ConstantExpression>[]; |
439 List<ConstantExpression> valueExpressions = <ConstantExpression>[]; | 435 List<ConstantExpression> valueExpressions = <ConstantExpression>[]; |
(...skipping 15 matching lines...) Expand all Loading... |
455 keyValues.add(key.value); | 451 keyValues.add(key.value); |
456 } else { | 452 } else { |
457 reporter.reportWarningMessage( | 453 reporter.reportWarningMessage( |
458 entry.key, MessageKind.EQUAL_MAP_ENTRY_KEY); | 454 entry.key, MessageKind.EQUAL_MAP_ENTRY_KEY); |
459 } | 455 } |
460 keyExpressions.add(key.expression); | 456 keyExpressions.add(key.expression); |
461 valueExpressions.add(value.expression); | 457 valueExpressions.add(value.expression); |
462 map[key.value] = value.value; | 458 map[key.value] = value.value; |
463 } | 459 } |
464 InterfaceType type = elements.getType(node); | 460 InterfaceType type = elements.getType(node); |
465 return new AstConstant(context, node, | 461 return new AstConstant( |
| 462 context, |
| 463 node, |
466 new MapConstantExpression(type, keyExpressions, valueExpressions), | 464 new MapConstantExpression(type, keyExpressions, valueExpressions), |
467 constantSystem.createMap( | 465 constantSystem.createMap( |
468 compiler, type, keyValues, map.values.toList())); | 466 compiler, type, keyValues, map.values.toList())); |
469 } | 467 } |
470 | 468 |
471 AstConstant visitLiteralNull(LiteralNull node) { | 469 AstConstant visitLiteralNull(LiteralNull node) { |
472 return new AstConstant(context, node, new NullConstantExpression(), | 470 return new AstConstant(context, node, new NullConstantExpression(), |
473 constantSystem.createNull()); | 471 constantSystem.createNull()); |
474 } | 472 } |
475 | 473 |
476 AstConstant visitLiteralString(LiteralString node) { | 474 AstConstant visitLiteralString(LiteralString node) { |
477 return new AstConstant(context, node, | 475 return new AstConstant( |
| 476 context, |
| 477 node, |
478 new StringConstantExpression(node.dartString.slowToString()), | 478 new StringConstantExpression(node.dartString.slowToString()), |
479 constantSystem.createString(node.dartString)); | 479 constantSystem.createString(node.dartString)); |
480 } | 480 } |
481 | 481 |
482 AstConstant visitStringJuxtaposition(StringJuxtaposition node) { | 482 AstConstant visitStringJuxtaposition(StringJuxtaposition node) { |
483 AstConstant left = evaluate(node.first); | 483 AstConstant left = evaluate(node.first); |
484 AstConstant right = evaluate(node.second); | 484 AstConstant right = evaluate(node.second); |
485 if (left == null || right == null) return null; | 485 if (left == null || right == null) return null; |
486 StringConstantValue leftValue = left.value; | 486 StringConstantValue leftValue = left.value; |
487 StringConstantValue rightValue = right.value; | 487 StringConstantValue rightValue = right.value; |
488 return new AstConstant(context, node, | 488 return new AstConstant( |
| 489 context, |
| 490 node, |
489 new ConcatenateConstantExpression([left.expression, right.expression]), | 491 new ConcatenateConstantExpression([left.expression, right.expression]), |
490 constantSystem.createString(new DartString.concat( | 492 constantSystem.createString(new DartString.concat( |
491 leftValue.primitiveValue, rightValue.primitiveValue))); | 493 leftValue.primitiveValue, rightValue.primitiveValue))); |
492 } | 494 } |
493 | 495 |
494 AstConstant visitStringInterpolation(StringInterpolation node) { | 496 AstConstant visitStringInterpolation(StringInterpolation node) { |
495 List<ConstantExpression> subexpressions = <ConstantExpression>[]; | 497 List<ConstantExpression> subexpressions = <ConstantExpression>[]; |
496 AstConstant initialString = evaluate(node.string); | 498 AstConstant initialString = evaluate(node.string); |
497 if (initialString == null) { | 499 if (initialString == null) { |
498 return null; | 500 return null; |
(...skipping 23 matching lines...) Expand all Loading... |
522 } | 524 } |
523 accumulator = new DartString.concat(accumulator, expressionString); | 525 accumulator = new DartString.concat(accumulator, expressionString); |
524 AstConstant partString = evaluate(part.string); | 526 AstConstant partString = evaluate(part.string); |
525 if (partString == null) return null; | 527 if (partString == null) return null; |
526 subexpressions.add(partString.expression); | 528 subexpressions.add(partString.expression); |
527 StringConstantValue partStringValue = partString.value; | 529 StringConstantValue partStringValue = partString.value; |
528 accumulator = | 530 accumulator = |
529 new DartString.concat(accumulator, partStringValue.primitiveValue); | 531 new DartString.concat(accumulator, partStringValue.primitiveValue); |
530 } | 532 } |
531 ; | 533 ; |
532 return new AstConstant(context, node, | 534 return new AstConstant( |
| 535 context, |
| 536 node, |
533 new ConcatenateConstantExpression(subexpressions), | 537 new ConcatenateConstantExpression(subexpressions), |
534 constantSystem.createString(accumulator)); | 538 constantSystem.createString(accumulator)); |
535 } | 539 } |
536 | 540 |
537 AstConstant visitLiteralSymbol(LiteralSymbol node) { | 541 AstConstant visitLiteralSymbol(LiteralSymbol node) { |
538 InterfaceType type = coreTypes.symbolType; | 542 InterfaceType type = coreTypes.symbolType; |
539 String text = node.slowNameString; | 543 String text = node.slowNameString; |
540 List<AstConstant> arguments = <AstConstant>[ | 544 List<AstConstant> arguments = <AstConstant>[ |
541 new AstConstant(context, node, new StringConstantExpression(text), | 545 new AstConstant(context, node, new StringConstantExpression(text), |
542 constantSystem.createString(new LiteralDartString(text))) | 546 constantSystem.createString(new LiteralDartString(text))) |
(...skipping 30 matching lines...) Expand all Loading... |
573 } | 577 } |
574 | 578 |
575 // TODO(floitsch): provide better error-messages. | 579 // TODO(floitsch): provide better error-messages. |
576 AstConstant visitSend(Send send) { | 580 AstConstant visitSend(Send send) { |
577 Element element = elements[send]; | 581 Element element = elements[send]; |
578 if (send.isPropertyAccess) { | 582 if (send.isPropertyAccess) { |
579 AstConstant result; | 583 AstConstant result; |
580 if (Elements.isStaticOrTopLevelFunction(element)) { | 584 if (Elements.isStaticOrTopLevelFunction(element)) { |
581 FunctionElementX function = element; | 585 FunctionElementX function = element; |
582 function.computeType(resolution); | 586 function.computeType(resolution); |
583 result = new AstConstant(context, send, | 587 result = new AstConstant( |
| 588 context, |
| 589 send, |
584 new FunctionConstantExpression(function), | 590 new FunctionConstantExpression(function), |
585 new FunctionConstantValue(function)); | 591 new FunctionConstantValue(function)); |
586 } else if (Elements.isStaticOrTopLevelField(element)) { | 592 } else if (Elements.isStaticOrTopLevelField(element)) { |
587 ConstantExpression elementExpression; | 593 ConstantExpression elementExpression; |
588 if (element.isConst) { | 594 if (element.isConst) { |
589 elementExpression = handler.compileConstant(element); | 595 elementExpression = handler.compileConstant(element); |
590 } else if (element.isFinal && !isEvaluatingConstant) { | 596 } else if (element.isFinal && !isEvaluatingConstant) { |
591 elementExpression = handler.compileVariable(element); | 597 elementExpression = handler.compileVariable(element); |
592 } | 598 } |
593 if (elementExpression != null) { | 599 if (elementExpression != null) { |
594 result = new AstConstant(context, send, | 600 result = new AstConstant( |
| 601 context, |
| 602 send, |
595 new VariableConstantExpression(element), | 603 new VariableConstantExpression(element), |
596 handler.getConstantValue(elementExpression)); | 604 handler.getConstantValue(elementExpression)); |
597 } | 605 } |
598 } else if (Elements.isClass(element) || Elements.isTypedef(element)) { | 606 } else if (Elements.isClass(element) || Elements.isTypedef(element)) { |
599 assert(elements.isTypeLiteral(send)); | 607 assert(elements.isTypeLiteral(send)); |
600 DartType elementType = elements.getTypeLiteralType(send); | 608 DartType elementType = elements.getTypeLiteralType(send); |
601 result = new AstConstant(context, send, | 609 result = new AstConstant( |
| 610 context, |
| 611 send, |
602 new TypeConstantExpression(elementType), | 612 new TypeConstantExpression(elementType), |
603 makeTypeConstant(elementType)); | 613 makeTypeConstant(elementType)); |
604 } else if (send.receiver != null) { | 614 } else if (send.receiver != null) { |
605 if (send.selector.asIdentifier().source == "length") { | 615 if (send.selector.asIdentifier().source == "length") { |
606 AstConstant left = evaluate(send.receiver); | 616 AstConstant left = evaluate(send.receiver); |
607 if (left != null && left.value.isString) { | 617 if (left != null && left.value.isString) { |
608 StringConstantValue stringConstantValue = left.value; | 618 StringConstantValue stringConstantValue = left.value; |
609 DartString string = stringConstantValue.primitiveValue; | 619 DartString string = stringConstantValue.primitiveValue; |
610 IntConstantValue length = constantSystem.createInt(string.length); | 620 IntConstantValue length = constantSystem.createInt(string.length); |
611 result = new AstConstant(context, send, | 621 result = new AstConstant(context, send, |
612 new StringLengthConstantExpression(left.expression), length); | 622 new StringLengthConstantExpression(left.expression), length); |
613 } | 623 } |
614 } | 624 } |
615 // Fall through to error handling. | 625 // Fall through to error handling. |
616 } else if (!Elements.isUnresolved(element) && | 626 } else if (!Elements.isUnresolved(element) && |
617 element.isVariable && | 627 element.isVariable && |
618 element.isConst) { | 628 element.isConst) { |
619 ConstantExpression variableExpression = | 629 ConstantExpression variableExpression = |
620 handler.compileConstant(element); | 630 handler.compileConstant(element); |
621 if (variableExpression != null) { | 631 if (variableExpression != null) { |
622 result = new AstConstant(context, send, | 632 result = new AstConstant( |
| 633 context, |
| 634 send, |
623 new VariableConstantExpression(element), | 635 new VariableConstantExpression(element), |
624 handler.getConstantValue(variableExpression)); | 636 handler.getConstantValue(variableExpression)); |
625 } | 637 } |
626 } | 638 } |
627 if (result == null) { | 639 if (result == null) { |
628 return signalNotCompileTimeConstant(send); | 640 return signalNotCompileTimeConstant(send); |
629 } | 641 } |
630 if (isDeferredUse(send)) { | 642 if (isDeferredUse(send)) { |
631 if (isEvaluatingConstant) { | 643 if (isEvaluatingConstant) { |
632 reporter.reportErrorMessage( | 644 reporter.reportErrorMessage( |
633 send, MessageKind.DEFERRED_COMPILE_TIME_CONSTANT); | 645 send, MessageKind.DEFERRED_COMPILE_TIME_CONSTANT); |
634 } | 646 } |
635 PrefixElement prefix = | 647 PrefixElement prefix = |
636 compiler.deferredLoadTask.deferredPrefixElement(send, elements); | 648 compiler.deferredLoadTask.deferredPrefixElement(send, elements); |
637 result = new AstConstant(context, send, | 649 result = new AstConstant( |
| 650 context, |
| 651 send, |
638 new DeferredConstantExpression(result.expression, prefix), | 652 new DeferredConstantExpression(result.expression, prefix), |
639 new DeferredConstantValue(result.value, prefix)); | 653 new DeferredConstantValue(result.value, prefix)); |
640 compiler.deferredLoadTask.registerConstantDeferredUse( | 654 compiler.deferredLoadTask |
641 result.value, prefix); | 655 .registerConstantDeferredUse(result.value, prefix); |
642 } | 656 } |
643 return result; | 657 return result; |
644 } else if (send.isCall) { | 658 } else if (send.isCall) { |
645 if (element == compiler.identicalFunction && send.argumentCount() == 2) { | 659 if (element == compiler.identicalFunction && send.argumentCount() == 2) { |
646 AstConstant left = evaluate(send.argumentsNode.nodes.head); | 660 AstConstant left = evaluate(send.argumentsNode.nodes.head); |
647 AstConstant right = evaluate(send.argumentsNode.nodes.tail.head); | 661 AstConstant right = evaluate(send.argumentsNode.nodes.tail.head); |
648 if (left == null || right == null) { | 662 if (left == null || right == null) { |
649 return null; | 663 return null; |
650 } | 664 } |
651 ConstantValue result = | 665 ConstantValue result = |
652 constantSystem.identity.fold(left.value, right.value); | 666 constantSystem.identity.fold(left.value, right.value); |
653 if (result != null) { | 667 if (result != null) { |
654 return new AstConstant(context, send, new IdenticalConstantExpression( | 668 return new AstConstant( |
655 left.expression, right.expression), result); | 669 context, |
| 670 send, |
| 671 new IdenticalConstantExpression( |
| 672 left.expression, right.expression), |
| 673 result); |
656 } | 674 } |
657 } | 675 } |
658 return signalNotCompileTimeConstant(send); | 676 return signalNotCompileTimeConstant(send); |
659 } else if (send.isPrefix) { | 677 } else if (send.isPrefix) { |
660 assert(send.isOperator); | 678 assert(send.isOperator); |
661 AstConstant receiverConstant = evaluate(send.receiver); | 679 AstConstant receiverConstant = evaluate(send.receiver); |
662 if (receiverConstant == null) { | 680 if (receiverConstant == null) { |
663 return null; | 681 return null; |
664 } | 682 } |
665 Operator node = send.selector; | 683 Operator node = send.selector; |
666 UnaryOperator operator = UnaryOperator.parse(node.source); | 684 UnaryOperator operator = UnaryOperator.parse(node.source); |
667 UnaryOperation operation = constantSystem.lookupUnary(operator); | 685 UnaryOperation operation = constantSystem.lookupUnary(operator); |
668 if (operation == null) { | 686 if (operation == null) { |
669 reporter.internalError(send.selector, "Unexpected operator."); | 687 reporter.internalError(send.selector, "Unexpected operator."); |
670 } | 688 } |
671 ConstantValue folded = operation.fold(receiverConstant.value); | 689 ConstantValue folded = operation.fold(receiverConstant.value); |
672 if (folded == null) { | 690 if (folded == null) { |
673 return signalNotCompileTimeConstant(send); | 691 return signalNotCompileTimeConstant(send); |
674 } | 692 } |
675 return new AstConstant(context, send, | 693 return new AstConstant( |
| 694 context, |
| 695 send, |
676 new UnaryConstantExpression(operator, receiverConstant.expression), | 696 new UnaryConstantExpression(operator, receiverConstant.expression), |
677 folded); | 697 folded); |
678 } else if (send.isOperator && !send.isPostfix) { | 698 } else if (send.isOperator && !send.isPostfix) { |
679 assert(send.argumentCount() == 1); | 699 assert(send.argumentCount() == 1); |
680 AstConstant left = evaluate(send.receiver); | 700 AstConstant left = evaluate(send.receiver); |
681 AstConstant right = evaluate(send.argumentsNode.nodes.head); | 701 AstConstant right = evaluate(send.argumentsNode.nodes.head); |
682 if (left == null || right == null) { | 702 if (left == null || right == null) { |
683 return null; | 703 return null; |
684 } | 704 } |
685 ConstantValue leftValue = left.value; | 705 ConstantValue leftValue = left.value; |
(...skipping 23 matching lines...) Expand all Loading... |
709 default: | 729 default: |
710 BinaryOperation operation = constantSystem.lookupBinary(operator); | 730 BinaryOperation operation = constantSystem.lookupBinary(operator); |
711 if (operation != null) { | 731 if (operation != null) { |
712 folded = operation.fold(leftValue, rightValue); | 732 folded = operation.fold(leftValue, rightValue); |
713 } | 733 } |
714 } | 734 } |
715 } | 735 } |
716 if (folded == null) { | 736 if (folded == null) { |
717 return signalNotCompileTimeConstant(send); | 737 return signalNotCompileTimeConstant(send); |
718 } | 738 } |
719 return new AstConstant(context, send, new BinaryConstantExpression( | 739 return new AstConstant( |
720 left.expression, operator, right.expression), folded); | 740 context, |
| 741 send, |
| 742 new BinaryConstantExpression( |
| 743 left.expression, operator, right.expression), |
| 744 folded); |
721 } | 745 } |
722 return signalNotCompileTimeConstant(send); | 746 return signalNotCompileTimeConstant(send); |
723 } | 747 } |
724 | 748 |
725 AstConstant visitConditional(Conditional node) { | 749 AstConstant visitConditional(Conditional node) { |
726 AstConstant condition = evaluate(node.condition); | 750 AstConstant condition = evaluate(node.condition); |
727 if (condition == null) { | 751 if (condition == null) { |
728 return null; | 752 return null; |
729 } else if (!condition.value.isBool) { | 753 } else if (!condition.value.isBool) { |
730 DartType conditionType = condition.value.getType(coreTypes); | 754 DartType conditionType = condition.value.getType(coreTypes); |
731 if (isEvaluatingConstant) { | 755 if (isEvaluatingConstant) { |
732 reporter.reportErrorMessage( | 756 reporter.reportErrorMessage(node.condition, MessageKind.NOT_ASSIGNABLE, |
733 node.condition, | 757 {'fromType': conditionType, 'toType': coreTypes.boolType}); |
734 MessageKind.NOT_ASSIGNABLE, | |
735 {'fromType': conditionType, | |
736 'toType': coreTypes.boolType}); | |
737 return new ErroneousAstConstant(context, node); | 758 return new ErroneousAstConstant(context, node); |
738 } | 759 } |
739 return null; | 760 return null; |
740 } | 761 } |
741 AstConstant thenExpression = evaluate(node.thenExpression); | 762 AstConstant thenExpression = evaluate(node.thenExpression); |
742 AstConstant elseExpression = evaluate(node.elseExpression); | 763 AstConstant elseExpression = evaluate(node.elseExpression); |
743 if (thenExpression == null || elseExpression == null) { | 764 if (thenExpression == null || elseExpression == null) { |
744 return null; | 765 return null; |
745 } | 766 } |
746 BoolConstantValue boolCondition = condition.value; | 767 BoolConstantValue boolCondition = condition.value; |
747 return new AstConstant(context, node, new ConditionalConstantExpression( | 768 return new AstConstant( |
748 condition.expression, thenExpression.expression, | 769 context, |
749 elseExpression.expression), boolCondition.primitiveValue | 770 node, |
750 ? thenExpression.value | 771 new ConditionalConstantExpression(condition.expression, |
751 : elseExpression.value); | 772 thenExpression.expression, elseExpression.expression), |
| 773 boolCondition.primitiveValue |
| 774 ? thenExpression.value |
| 775 : elseExpression.value); |
752 } | 776 } |
753 | 777 |
754 AstConstant visitSendSet(SendSet node) { | 778 AstConstant visitSendSet(SendSet node) { |
755 return signalNotCompileTimeConstant(node); | 779 return signalNotCompileTimeConstant(node); |
756 } | 780 } |
757 | 781 |
758 /** | 782 /** |
759 * Returns the normalized list of constant arguments that are passed to the | 783 * Returns the normalized list of constant arguments that are passed to the |
760 * constructor including both the concrete arguments and default values for | 784 * constructor including both the concrete arguments and default values for |
761 * omitted optional arguments. | 785 * omitted optional arguments. |
762 * | 786 * |
763 * Invariant: [target] must be an implementation element. | 787 * Invariant: [target] must be an implementation element. |
764 */ | 788 */ |
765 List<AstConstant> evaluateArgumentsToConstructor(Node node, | 789 List<AstConstant> evaluateArgumentsToConstructor( |
766 CallStructure callStructure, Link<Node> arguments, | 790 Node node, |
767 ConstructorElement target, {AstConstant compileArgument(Node node)}) { | 791 CallStructure callStructure, |
| 792 Link<Node> arguments, |
| 793 ConstructorElement target, |
| 794 {AstConstant compileArgument(Node node)}) { |
768 assert(invariant(node, target.isImplementation)); | 795 assert(invariant(node, target.isImplementation)); |
769 | 796 |
770 AstConstant compileDefaultValue(VariableElement element) { | 797 AstConstant compileDefaultValue(VariableElement element) { |
771 ConstantExpression constant = handler.compileConstant(element); | 798 ConstantExpression constant = handler.compileConstant(element); |
772 return new AstConstant.fromDefaultValue( | 799 return new AstConstant.fromDefaultValue( |
773 element, constant, handler.getConstantValue(constant)); | 800 element, constant, handler.getConstantValue(constant)); |
774 } | 801 } |
775 target.computeType(resolution); | 802 target.computeType(resolution); |
776 | 803 |
777 FunctionSignature signature = target.functionSignature; | 804 FunctionSignature signature = target.functionSignature; |
778 if (!callStructure.signatureApplies(signature)) { | 805 if (!callStructure.signatureApplies(signature)) { |
779 String name = Elements.constructorNameForDiagnostics( | 806 String name = Elements.constructorNameForDiagnostics( |
780 target.enclosingClass.name, target.name); | 807 target.enclosingClass.name, target.name); |
781 reporter.reportErrorMessage( | 808 reporter.reportErrorMessage(node, |
782 node, MessageKind.INVALID_CONSTRUCTOR_ARGUMENTS, | 809 MessageKind.INVALID_CONSTRUCTOR_ARGUMENTS, {'constructorName': name}); |
783 {'constructorName': name}); | |
784 | 810 |
785 return new List<AstConstant>.filled( | 811 return new List<AstConstant>.filled( |
786 target.functionSignature.parameterCount, | 812 target.functionSignature.parameterCount, |
787 new ErroneousAstConstant(context, node)); | 813 new ErroneousAstConstant(context, node)); |
788 } | 814 } |
789 return callStructure.makeArgumentsList( | 815 return callStructure.makeArgumentsList( |
790 arguments, target, compileArgument, compileDefaultValue); | 816 arguments, target, compileArgument, compileDefaultValue); |
791 } | 817 } |
792 | 818 |
793 AstConstant visitNewExpression(NewExpression node) { | 819 AstConstant visitNewExpression(NewExpression node) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
827 // a post-process action, so we have to make sure it is done here. | 853 // a post-process action, so we have to make sure it is done here. |
828 compiler.resolver.resolveRedirectionChain(constructor, node); | 854 compiler.resolver.resolveRedirectionChain(constructor, node); |
829 | 855 |
830 bool isInvalid = false; | 856 bool isInvalid = false; |
831 InterfaceType constructedType = type; | 857 InterfaceType constructedType = type; |
832 ConstructorElement implementation; | 858 ConstructorElement implementation; |
833 if (constructor.isRedirectingFactory) { | 859 if (constructor.isRedirectingFactory) { |
834 if (constructor.isEffectiveTargetMalformed) { | 860 if (constructor.isEffectiveTargetMalformed) { |
835 isInvalid = true; | 861 isInvalid = true; |
836 } else { | 862 } else { |
837 constructedType = | 863 constructedType = constructor.computeEffectiveTargetType(type); |
838 constructor.computeEffectiveTargetType(type); | |
839 ConstructorElement target = constructor.effectiveTarget; | 864 ConstructorElement target = constructor.effectiveTarget; |
840 // The constructor must be an implementation to ensure that field | 865 // The constructor must be an implementation to ensure that field |
841 // initializers are handled correctly. | 866 // initializers are handled correctly. |
842 implementation = target.implementation; | 867 implementation = target.implementation; |
843 } | 868 } |
844 } else { | 869 } else { |
845 // The constructor must be an implementation to ensure that field | 870 // The constructor must be an implementation to ensure that field |
846 // initializers are handled correctly. | 871 // initializers are handled correctly. |
847 implementation = constructor.implementation; | 872 implementation = constructor.implementation; |
848 isInvalid = implementation.isMalformed; | 873 isInvalid = implementation.isMalformed; |
(...skipping 26 matching lines...) Expand all Loading... |
875 assert(normalizedArguments != null); | 900 assert(normalizedArguments != null); |
876 concreteArguments = normalizedArguments; | 901 concreteArguments = normalizedArguments; |
877 } | 902 } |
878 | 903 |
879 if (constructor == compiler.intEnvironment || | 904 if (constructor == compiler.intEnvironment || |
880 constructor == compiler.boolEnvironment || | 905 constructor == compiler.boolEnvironment || |
881 constructor == compiler.stringEnvironment) { | 906 constructor == compiler.stringEnvironment) { |
882 return createFromEnvironmentConstant(node, constructedType, constructor, | 907 return createFromEnvironmentConstant(node, constructedType, constructor, |
883 callStructure, normalizedArguments, concreteArguments); | 908 callStructure, normalizedArguments, concreteArguments); |
884 } else { | 909 } else { |
885 return makeConstructedConstant(compiler, handler, context, node, type, | 910 return makeConstructedConstant( |
886 constructor, constructedType, implementation, callStructure, | 911 compiler, |
887 concreteArguments, normalizedArguments); | 912 handler, |
| 913 context, |
| 914 node, |
| 915 type, |
| 916 constructor, |
| 917 constructedType, |
| 918 implementation, |
| 919 callStructure, |
| 920 concreteArguments, |
| 921 normalizedArguments); |
888 } | 922 } |
889 } | 923 } |
890 | 924 |
891 AstConstant createFromEnvironmentConstant(Node node, InterfaceType type, | 925 AstConstant createFromEnvironmentConstant( |
892 ConstructorElement constructor, CallStructure callStructure, | 926 Node node, |
| 927 InterfaceType type, |
| 928 ConstructorElement constructor, |
| 929 CallStructure callStructure, |
893 List<AstConstant> normalizedArguments, | 930 List<AstConstant> normalizedArguments, |
894 List<AstConstant> concreteArguments) { | 931 List<AstConstant> concreteArguments) { |
895 var firstArgument = normalizedArguments[0].value; | 932 var firstArgument = normalizedArguments[0].value; |
896 ConstantValue defaultValue = normalizedArguments[1].value; | 933 ConstantValue defaultValue = normalizedArguments[1].value; |
897 | 934 |
898 if (firstArgument.isNull) { | 935 if (firstArgument.isNull) { |
899 reporter.reportErrorMessage( | 936 reporter.reportErrorMessage( |
900 normalizedArguments[0].node, MessageKind.NULL_NOT_ALLOWED); | 937 normalizedArguments[0].node, MessageKind.NULL_NOT_ALLOWED); |
901 return null; | 938 return null; |
902 } | 939 } |
903 | 940 |
904 if (!firstArgument.isString) { | 941 if (!firstArgument.isString) { |
905 DartType type = defaultValue.getType(coreTypes); | 942 DartType type = defaultValue.getType(coreTypes); |
906 reporter.reportErrorMessage( | 943 reporter.reportErrorMessage( |
907 normalizedArguments[0].node, | 944 normalizedArguments[0].node, |
908 MessageKind.NOT_ASSIGNABLE, | 945 MessageKind.NOT_ASSIGNABLE, |
909 {'fromType': type, | 946 {'fromType': type, 'toType': coreTypes.stringType}); |
910 'toType': coreTypes.stringType}); | |
911 return null; | 947 return null; |
912 } | 948 } |
913 | 949 |
914 if (constructor == compiler.intEnvironment && | 950 if (constructor == compiler.intEnvironment && |
915 !(defaultValue.isNull || defaultValue.isInt)) { | 951 !(defaultValue.isNull || defaultValue.isInt)) { |
916 DartType type = defaultValue.getType(coreTypes); | 952 DartType type = defaultValue.getType(coreTypes); |
917 reporter.reportErrorMessage( | 953 reporter.reportErrorMessage( |
918 normalizedArguments[1].node, | 954 normalizedArguments[1].node, |
919 MessageKind.NOT_ASSIGNABLE, | 955 MessageKind.NOT_ASSIGNABLE, |
920 {'fromType': type, | 956 {'fromType': type, 'toType': coreTypes.intType}); |
921 'toType': coreTypes.intType}); | |
922 return null; | 957 return null; |
923 } | 958 } |
924 | 959 |
925 if (constructor == compiler.boolEnvironment && | 960 if (constructor == compiler.boolEnvironment && |
926 !(defaultValue.isNull || defaultValue.isBool)) { | 961 !(defaultValue.isNull || defaultValue.isBool)) { |
927 DartType type = defaultValue.getType(coreTypes); | 962 DartType type = defaultValue.getType(coreTypes); |
928 reporter.reportErrorMessage( | 963 reporter.reportErrorMessage( |
929 normalizedArguments[1].node, | 964 normalizedArguments[1].node, |
930 MessageKind.NOT_ASSIGNABLE, | 965 MessageKind.NOT_ASSIGNABLE, |
931 {'fromType': type, | 966 {'fromType': type, 'toType': coreTypes.boolType}); |
932 'toType': coreTypes.boolType}); | |
933 return null; | 967 return null; |
934 } | 968 } |
935 | 969 |
936 if (constructor == compiler.stringEnvironment && | 970 if (constructor == compiler.stringEnvironment && |
937 !(defaultValue.isNull || defaultValue.isString)) { | 971 !(defaultValue.isNull || defaultValue.isString)) { |
938 DartType type = defaultValue.getType(coreTypes); | 972 DartType type = defaultValue.getType(coreTypes); |
939 reporter.reportErrorMessage( | 973 reporter.reportErrorMessage( |
940 normalizedArguments[1].node, | 974 normalizedArguments[1].node, |
941 MessageKind.NOT_ASSIGNABLE, | 975 MessageKind.NOT_ASSIGNABLE, |
942 {'fromType': type, | 976 {'fromType': type, 'toType': coreTypes.stringType}); |
943 'toType': coreTypes.stringType}); | |
944 return null; | 977 return null; |
945 } | 978 } |
946 | 979 |
947 String name = firstArgument.primitiveValue.slowToString(); | 980 String name = firstArgument.primitiveValue.slowToString(); |
948 String value = compiler.fromEnvironment(name); | 981 String value = compiler.fromEnvironment(name); |
949 | 982 |
950 AstConstant createEvaluatedConstant(ConstantValue value) { | 983 AstConstant createEvaluatedConstant(ConstantValue value) { |
951 ConstantExpression expression; | 984 ConstantExpression expression; |
952 ConstantExpression name = concreteArguments[0].expression; | 985 ConstantExpression name = concreteArguments[0].expression; |
953 ConstantExpression defaultValue; | 986 ConstantExpression defaultValue; |
(...skipping 28 matching lines...) Expand all Loading... |
982 } else { | 1015 } else { |
983 return createEvaluatedConstant(defaultValue); | 1016 return createEvaluatedConstant(defaultValue); |
984 } | 1017 } |
985 } else { | 1018 } else { |
986 assert(constructor == compiler.stringEnvironment); | 1019 assert(constructor == compiler.stringEnvironment); |
987 return createEvaluatedConstant( | 1020 return createEvaluatedConstant( |
988 constantSystem.createString(new DartString.literal(value))); | 1021 constantSystem.createString(new DartString.literal(value))); |
989 } | 1022 } |
990 } | 1023 } |
991 | 1024 |
992 static AstConstant makeConstructedConstant(Compiler compiler, | 1025 static AstConstant makeConstructedConstant( |
993 ConstantCompilerBase handler, Element context, Node node, | 1026 Compiler compiler, |
994 InterfaceType type, ConstructorElement constructor, | 1027 ConstantCompilerBase handler, |
995 InterfaceType constructedType, ConstructorElement target, | 1028 Element context, |
996 CallStructure callStructure, List<AstConstant> concreteArguments, | 1029 Node node, |
| 1030 InterfaceType type, |
| 1031 ConstructorElement constructor, |
| 1032 InterfaceType constructedType, |
| 1033 ConstructorElement target, |
| 1034 CallStructure callStructure, |
| 1035 List<AstConstant> concreteArguments, |
997 List<AstConstant> normalizedArguments) { | 1036 List<AstConstant> normalizedArguments) { |
998 if (target.isRedirectingFactory) { | 1037 if (target.isRedirectingFactory) { |
999 // This happens is case of cyclic redirection. | 1038 // This happens is case of cyclic redirection. |
1000 assert(invariant(node, compiler.compilationFailed, | 1039 assert(invariant(node, compiler.compilationFailed, |
1001 message: "makeConstructedConstant can only be called with the " | 1040 message: "makeConstructedConstant can only be called with the " |
1002 "effective target: $constructor")); | 1041 "effective target: $constructor")); |
1003 return new ErroneousAstConstant(context, node); | 1042 return new ErroneousAstConstant(context, node); |
1004 } | 1043 } |
1005 assert(invariant(node, | 1044 assert(invariant( |
| 1045 node, |
1006 callStructure.signatureApplies(constructor.functionSignature) || | 1046 callStructure.signatureApplies(constructor.functionSignature) || |
1007 compiler.compilationFailed, | 1047 compiler.compilationFailed, |
1008 message: "Call structure $callStructure does not apply to constructor " | 1048 message: "Call structure $callStructure does not apply to constructor " |
1009 "$constructor.")); | 1049 "$constructor.")); |
1010 | 1050 |
1011 ConstructorEvaluator evaluator = | 1051 ConstructorEvaluator evaluator = |
1012 new ConstructorEvaluator(constructedType, target, handler, compiler); | 1052 new ConstructorEvaluator(constructedType, target, handler, compiler); |
1013 evaluator.evaluateConstructorFieldValues(normalizedArguments); | 1053 evaluator.evaluateConstructorFieldValues(normalizedArguments); |
1014 Map<FieldElement, AstConstant> fieldConstants = | 1054 Map<FieldElement, AstConstant> fieldConstants = |
1015 evaluator.buildFieldConstants(target.enclosingClass); | 1055 evaluator.buildFieldConstants(target.enclosingClass); |
1016 Map<FieldElement, ConstantValue> fieldValues = | 1056 Map<FieldElement, ConstantValue> fieldValues = |
1017 <FieldElement, ConstantValue>{}; | 1057 <FieldElement, ConstantValue>{}; |
1018 fieldConstants.forEach((FieldElement field, AstConstant astConstant) { | 1058 fieldConstants.forEach((FieldElement field, AstConstant astConstant) { |
1019 fieldValues[field] = astConstant.value; | 1059 fieldValues[field] = astConstant.value; |
1020 }); | 1060 }); |
1021 return new AstConstant(context, node, new ConstructedConstantExpression( | 1061 return new AstConstant( |
1022 type, constructor, callStructure, | 1062 context, |
| 1063 node, |
| 1064 new ConstructedConstantExpression(type, constructor, callStructure, |
1023 concreteArguments.map((e) => e.expression).toList()), | 1065 concreteArguments.map((e) => e.expression).toList()), |
1024 new ConstructedConstantValue(constructedType, fieldValues)); | 1066 new ConstructedConstantValue(constructedType, fieldValues)); |
1025 } | 1067 } |
1026 | 1068 |
1027 AstConstant visitParenthesizedExpression(ParenthesizedExpression node) { | 1069 AstConstant visitParenthesizedExpression(ParenthesizedExpression node) { |
1028 return node.expression.accept(this); | 1070 return node.expression.accept(this); |
1029 } | 1071 } |
1030 | 1072 |
1031 AstConstant signalNotCompileTimeConstant(Node node, | 1073 AstConstant signalNotCompileTimeConstant(Node node, |
1032 {MessageKind message: MessageKind.NOT_A_COMPILE_TIME_CONSTANT}) { | 1074 {MessageKind message: MessageKind.NOT_A_COMPILE_TIME_CONSTANT}) { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1078 return super.visitSend(send); | 1120 return super.visitSend(send); |
1079 } | 1121 } |
1080 | 1122 |
1081 void potentiallyCheckType(TypedElement element, AstConstant constant) { | 1123 void potentiallyCheckType(TypedElement element, AstConstant constant) { |
1082 if (compiler.options.enableTypeAssertions) { | 1124 if (compiler.options.enableTypeAssertions) { |
1083 DartType elementType = element.type.substByContext(constructedType); | 1125 DartType elementType = element.type.substByContext(constructedType); |
1084 DartType constantType = constant.value.getType(coreTypes); | 1126 DartType constantType = constant.value.getType(coreTypes); |
1085 if (!constantSystem.isSubtype( | 1127 if (!constantSystem.isSubtype( |
1086 compiler.types, constantType, elementType)) { | 1128 compiler.types, constantType, elementType)) { |
1087 reporter.withCurrentElement(constant.element, () { | 1129 reporter.withCurrentElement(constant.element, () { |
1088 reporter.reportErrorMessage( | 1130 reporter.reportErrorMessage(constant.node, MessageKind.NOT_ASSIGNABLE, |
1089 constant.node, | 1131 {'fromType': constantType, 'toType': elementType}); |
1090 MessageKind.NOT_ASSIGNABLE, | |
1091 {'fromType': constantType, | |
1092 'toType': elementType}); | |
1093 }); | 1132 }); |
1094 } | 1133 } |
1095 } | 1134 } |
1096 } | 1135 } |
1097 | 1136 |
1098 void updateFieldValue(Node node, TypedElement element, AstConstant constant) { | 1137 void updateFieldValue(Node node, TypedElement element, AstConstant constant) { |
1099 potentiallyCheckType(element, constant); | 1138 potentiallyCheckType(element, constant); |
1100 fieldValues[element] = constant; | 1139 fieldValues[element] = constant; |
1101 } | 1140 } |
1102 | 1141 |
(...skipping 17 matching lines...) Expand all Loading... |
1120 potentiallyCheckType(parameter, argument); | 1159 potentiallyCheckType(parameter, argument); |
1121 definitions[parameter] = argument; | 1160 definitions[parameter] = argument; |
1122 } | 1161 } |
1123 }); | 1162 }); |
1124 } | 1163 } |
1125 | 1164 |
1126 void evaluateSuperOrRedirectSend( | 1165 void evaluateSuperOrRedirectSend( |
1127 List<AstConstant> compiledArguments, FunctionElement targetConstructor) { | 1166 List<AstConstant> compiledArguments, FunctionElement targetConstructor) { |
1128 ConstructorEvaluator evaluator = new ConstructorEvaluator( | 1167 ConstructorEvaluator evaluator = new ConstructorEvaluator( |
1129 constructedType.asInstanceOf(targetConstructor.enclosingClass), | 1168 constructedType.asInstanceOf(targetConstructor.enclosingClass), |
1130 targetConstructor, handler, compiler); | 1169 targetConstructor, |
| 1170 handler, |
| 1171 compiler); |
1131 evaluator.evaluateConstructorFieldValues(compiledArguments); | 1172 evaluator.evaluateConstructorFieldValues(compiledArguments); |
1132 // Copy over the fieldValues from the super/redirect-constructor. | 1173 // Copy over the fieldValues from the super/redirect-constructor. |
1133 // No need to go through [updateFieldValue] because the | 1174 // No need to go through [updateFieldValue] because the |
1134 // assignments have already been checked in checked mode. | 1175 // assignments have already been checked in checked mode. |
1135 evaluator.fieldValues.forEach((key, value) => fieldValues[key] = value); | 1176 evaluator.fieldValues.forEach((key, value) => fieldValues[key] = value); |
1136 } | 1177 } |
1137 | 1178 |
1138 /** | 1179 /** |
1139 * Runs through the initializers of the given [constructor] and updates | 1180 * Runs through the initializers of the given [constructor] and updates |
1140 * the [fieldValues] map. | 1181 * the [fieldValues] map. |
(...skipping 20 matching lines...) Expand all Loading... |
1161 !link.isEmpty; | 1202 !link.isEmpty; |
1162 link = link.tail) { | 1203 link = link.tail) { |
1163 assert(link.head is Send); | 1204 assert(link.head is Send); |
1164 if (link.head is! SendSet) { | 1205 if (link.head is! SendSet) { |
1165 // A super initializer or constructor redirection. | 1206 // A super initializer or constructor redirection. |
1166 Send call = link.head; | 1207 Send call = link.head; |
1167 FunctionElement target = elements[call]; | 1208 FunctionElement target = elements[call]; |
1168 if (!target.isMalformed) { | 1209 if (!target.isMalformed) { |
1169 List<AstConstant> compiledArguments = | 1210 List<AstConstant> compiledArguments = |
1170 evaluateArgumentsToConstructor( | 1211 evaluateArgumentsToConstructor( |
1171 call, | 1212 call, |
1172 elements.getSelector(call).callStructure, | 1213 elements.getSelector(call).callStructure, |
1173 call.arguments, | 1214 call.arguments, |
1174 target, | 1215 target, |
1175 compileArgument: evaluateConstant); | 1216 compileArgument: evaluateConstant); |
1176 evaluateSuperOrRedirectSend(compiledArguments, target); | 1217 evaluateSuperOrRedirectSend(compiledArguments, target); |
1177 } | 1218 } |
1178 foundSuperOrRedirect = true; | 1219 foundSuperOrRedirect = true; |
1179 } else { | 1220 } else { |
1180 // A field initializer. | 1221 // A field initializer. |
1181 SendSet init = link.head; | 1222 SendSet init = link.head; |
1182 Link<Node> initArguments = init.arguments; | 1223 Link<Node> initArguments = init.arguments; |
1183 assert(!initArguments.isEmpty && initArguments.tail.isEmpty); | 1224 assert(!initArguments.isEmpty && initArguments.tail.isEmpty); |
1184 AstConstant fieldValue = evaluate(initArguments.head); | 1225 AstConstant fieldValue = evaluate(initArguments.head); |
1185 updateFieldValue(init, elements[init], fieldValue); | 1226 updateFieldValue(init, elements[init], fieldValue); |
1186 } | 1227 } |
1187 } | 1228 } |
1188 } | 1229 } |
1189 | 1230 |
1190 if (!foundSuperOrRedirect) { | 1231 if (!foundSuperOrRedirect) { |
1191 // No super initializer found. Try to find the default constructor if | 1232 // No super initializer found. Try to find the default constructor if |
1192 // the class is not Object. | 1233 // the class is not Object. |
1193 ClassElement enclosingClass = constructor.enclosingClass; | 1234 ClassElement enclosingClass = constructor.enclosingClass; |
1194 ClassElement superClass = enclosingClass.superclass; | 1235 ClassElement superClass = enclosingClass.superclass; |
1195 if (!enclosingClass.isObject) { | 1236 if (!enclosingClass.isObject) { |
1196 assert(superClass != null); | 1237 assert(superClass != null); |
1197 assert(superClass.isResolved); | 1238 assert(superClass.isResolved); |
1198 | 1239 |
1199 FunctionElement targetConstructor = | 1240 FunctionElement targetConstructor = |
1200 superClass.lookupDefaultConstructor(); | 1241 superClass.lookupDefaultConstructor(); |
1201 // If we do not find a default constructor, an error was reported | 1242 // If we do not find a default constructor, an error was reported |
1202 // already and compilation will fail anyway. So just ignore that case. | 1243 // already and compilation will fail anyway. So just ignore that case. |
1203 if (targetConstructor != null) { | 1244 if (targetConstructor != null) { |
1204 List<AstConstant> compiledArguments = evaluateArgumentsToConstructor( | 1245 List<AstConstant> compiledArguments = evaluateArgumentsToConstructor( |
1205 functionNode, CallStructure.NO_ARGS, const Link<Node>(), | 1246 functionNode, |
| 1247 CallStructure.NO_ARGS, |
| 1248 const Link<Node>(), |
1206 targetConstructor); | 1249 targetConstructor); |
1207 evaluateSuperOrRedirectSend(compiledArguments, targetConstructor); | 1250 evaluateSuperOrRedirectSend(compiledArguments, targetConstructor); |
1208 } | 1251 } |
1209 } | 1252 } |
1210 } | 1253 } |
1211 } | 1254 } |
1212 | 1255 |
1213 /** | 1256 /** |
1214 * Simulates the execution of the [constructor] with the given | 1257 * Simulates the execution of the [constructor] with the given |
1215 * [arguments] to obtain the field values that need to be passed to the | 1258 * [arguments] to obtain the field values that need to be passed to the |
1216 * native JavaScript constructor. | 1259 * native JavaScript constructor. |
1217 */ | 1260 */ |
1218 void evaluateConstructorFieldValues(List<AstConstant> arguments) { | 1261 void evaluateConstructorFieldValues(List<AstConstant> arguments) { |
1219 if (constructor.isMalformed) return; | 1262 if (constructor.isMalformed) return; |
1220 reporter.withCurrentElement(constructor, () { | 1263 reporter.withCurrentElement(constructor, () { |
1221 assignArgumentsToParameters(arguments); | 1264 assignArgumentsToParameters(arguments); |
1222 evaluateConstructorInitializers(); | 1265 evaluateConstructorInitializers(); |
1223 }); | 1266 }); |
1224 } | 1267 } |
1225 | 1268 |
1226 /// Builds a normalized list of the constant values for each field in the | 1269 /// Builds a normalized list of the constant values for each field in the |
1227 /// inheritance chain of [classElement]. | 1270 /// inheritance chain of [classElement]. |
1228 Map<FieldElement, AstConstant> buildFieldConstants( | 1271 Map<FieldElement, AstConstant> buildFieldConstants( |
1229 ClassElement classElement) { | 1272 ClassElement classElement) { |
1230 Map<FieldElement, AstConstant> fieldConstants = <FieldElement, AstConstant>{ | 1273 Map<FieldElement, AstConstant> fieldConstants = |
1231 }; | 1274 <FieldElement, AstConstant>{}; |
1232 classElement.implementation | 1275 classElement.implementation.forEachInstanceField( |
1233 .forEachInstanceField((ClassElement enclosing, FieldElement field) { | 1276 (ClassElement enclosing, FieldElement field) { |
1234 AstConstant fieldValue = fieldValues[field]; | 1277 AstConstant fieldValue = fieldValues[field]; |
1235 if (fieldValue == null) { | 1278 if (fieldValue == null) { |
1236 // Use the default value. | 1279 // Use the default value. |
1237 ConstantExpression fieldExpression = | 1280 ConstantExpression fieldExpression = |
1238 handler.internalCompileVariable(field, true, false); | 1281 handler.internalCompileVariable(field, true, false); |
1239 fieldValue = new AstConstant.fromDefaultValue( | 1282 fieldValue = new AstConstant.fromDefaultValue( |
1240 field, fieldExpression, handler.getConstantValue(fieldExpression)); | 1283 field, fieldExpression, handler.getConstantValue(fieldExpression)); |
1241 // TODO(het): If the field value doesn't typecheck due to the type | 1284 // TODO(het): If the field value doesn't typecheck due to the type |
1242 // variable in the constructor invocation, then report the error on the | 1285 // variable in the constructor invocation, then report the error on the |
1243 // invocation rather than the field. | 1286 // invocation rather than the field. |
(...skipping 17 matching lines...) Expand all Loading... |
1261 class AstConstant { | 1304 class AstConstant { |
1262 final Element element; | 1305 final Element element; |
1263 final Node node; | 1306 final Node node; |
1264 final ConstantExpression expression; | 1307 final ConstantExpression expression; |
1265 final ConstantValue value; | 1308 final ConstantValue value; |
1266 | 1309 |
1267 AstConstant(this.element, this.node, this.expression, this.value); | 1310 AstConstant(this.element, this.node, this.expression, this.value); |
1268 | 1311 |
1269 factory AstConstant.fromDefaultValue(VariableElement element, | 1312 factory AstConstant.fromDefaultValue(VariableElement element, |
1270 ConstantExpression constant, ConstantValue value) { | 1313 ConstantExpression constant, ConstantValue value) { |
1271 return new AstConstant(element, element.initializer != null | 1314 return new AstConstant( |
1272 ? element.initializer | 1315 element, |
1273 : element.node, constant, value); | 1316 element.initializer != null ? element.initializer : element.node, |
| 1317 constant, |
| 1318 value); |
1274 } | 1319 } |
1275 | 1320 |
1276 String toString() => expression.toString(); | 1321 String toString() => expression.toString(); |
1277 } | 1322 } |
1278 | 1323 |
1279 /// A synthetic constant used to recover from errors. | 1324 /// A synthetic constant used to recover from errors. |
1280 class ErroneousAstConstant extends AstConstant { | 1325 class ErroneousAstConstant extends AstConstant { |
1281 ErroneousAstConstant(Element element, Node node) : super(element, node, | 1326 ErroneousAstConstant(Element element, Node node) |
1282 // TODO(johnniwinther): Return a [NonConstantValue] instead. | 1327 : super( |
1283 new ErroneousConstantExpression(), new NullConstantValue()); | 1328 element, |
| 1329 node, |
| 1330 // TODO(johnniwinther): Return a [NonConstantValue] instead. |
| 1331 new ErroneousConstantExpression(), |
| 1332 new NullConstantValue()); |
1284 } | 1333 } |
1285 | 1334 |
1286 // TODO(johnniwinther): Clean this up. | 1335 // TODO(johnniwinther): Clean this up. |
1287 TreeElements _analyzeElementEagerly(Compiler compiler, AstElement element) { | 1336 TreeElements _analyzeElementEagerly(Compiler compiler, AstElement element) { |
1288 compiler.resolution.computeWorldImpact(element.declaration); | 1337 compiler.resolution.computeWorldImpact(element.declaration); |
1289 return element.resolvedAst.elements; | 1338 return element.resolvedAst.elements; |
1290 } | 1339 } |
1291 | 1340 |
1292 class _CompilerEnvironment implements Environment { | 1341 class _CompilerEnvironment implements Environment { |
1293 final Compiler compiler; | 1342 final Compiler compiler; |
1294 | 1343 |
1295 _CompilerEnvironment(this.compiler); | 1344 _CompilerEnvironment(this.compiler); |
1296 | 1345 |
1297 @override | 1346 @override |
1298 String readFromEnvironment(String name) { | 1347 String readFromEnvironment(String name) { |
1299 return compiler.fromEnvironment(name); | 1348 return compiler.fromEnvironment(name); |
1300 } | 1349 } |
1301 } | 1350 } |
OLD | NEW |