Chromium Code Reviews| 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 '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'; |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 41 /// if possible. | 41 /// if possible. |
| 42 void compileVariable(VariableElement element); | 42 void compileVariable(VariableElement element); |
| 43 | 43 |
| 44 /// Compiles the compile-time constant for [node], or reports an error if | 44 /// Compiles the compile-time constant for [node], or reports an error if |
| 45 /// [node] is not a compile-time constant. | 45 /// [node] is not a compile-time constant. |
| 46 /// | 46 /// |
| 47 /// Depending on implementation, the constant compiler might also compute | 47 /// Depending on implementation, the constant compiler might also compute |
| 48 /// the compile-time constant for the backend interpretation of constants. | 48 /// the compile-time constant for the backend interpretation of constants. |
| 49 /// | 49 /// |
| 50 /// The returned constant is always of the frontend interpretation. | 50 /// The returned constant is always of the frontend interpretation. |
| 51 ConstantExpression compileNode(Node node, TreeElements elements); | 51 ConstantExpression compileNode(Node node, TreeElements elements, |
| 52 {bool enforceConst: true}); | |
|
Johnni Winther
2015/04/30 09:15:03
Document [enforceConst].
sigurdm
2015/04/30 11:21:44
Done.
| |
| 52 | 53 |
| 53 /// Compiles the compile-time constant for the value [metadata], or reports an | 54 /// Compiles the compile-time constant for the value [metadata], or reports an |
| 54 /// error if the value is not a compile-time constant. | 55 /// error if the value is not a compile-time constant. |
| 55 /// | 56 /// |
| 56 /// Depending on implementation, the constant compiler might also compute | 57 /// Depending on implementation, the constant compiler might also compute |
| 57 /// the compile-time constant for the backend interpretation of constants. | 58 /// the compile-time constant for the backend interpretation of constants. |
| 58 /// | 59 /// |
| 59 /// The returned constant is always of the frontend interpretation. | 60 /// The returned constant is always of the frontend interpretation. |
| 60 ConstantExpression compileMetadata(MetadataAnnotation metadata, | 61 ConstantExpression compileMetadata(MetadataAnnotation metadata, |
| 61 Node node, | 62 Node node, |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 206 ConstantExpression compileNodeWithDefinitions(Node node, | 207 ConstantExpression compileNodeWithDefinitions(Node node, |
| 207 TreeElements definitions, | 208 TreeElements definitions, |
| 208 {bool isConst: true}) { | 209 {bool isConst: true}) { |
| 209 assert(node != null); | 210 assert(node != null); |
| 210 CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator( | 211 CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator( |
| 211 this, definitions, compiler, isConst: isConst); | 212 this, definitions, compiler, isConst: isConst); |
| 212 AstConstant constant = evaluator.evaluate(node); | 213 AstConstant constant = evaluator.evaluate(node); |
| 213 return constant != null ? constant.expression : null; | 214 return constant != null ? constant.expression : null; |
| 214 } | 215 } |
| 215 | 216 |
| 216 ConstantExpression compileNode(Node node, TreeElements elements) { | 217 ConstantExpression compileNode(Node node, TreeElements elements, |
| 217 return compileNodeWithDefinitions(node, elements); | 218 {bool enforceConst: true}) { |
| 219 return compileNodeWithDefinitions(node, elements, isConst: enforceConst); | |
| 218 } | 220 } |
| 219 | 221 |
| 220 ConstantExpression compileMetadata(MetadataAnnotation metadata, | 222 ConstantExpression compileMetadata(MetadataAnnotation metadata, |
| 221 Node node, | 223 Node node, |
| 222 TreeElements elements) { | 224 TreeElements elements) { |
| 223 return compileNodeWithDefinitions(node, elements); | 225 return compileNodeWithDefinitions(node, elements); |
| 224 } | 226 } |
| 225 | 227 |
| 226 void forgetElement(Element element) { | 228 void forgetElement(Element element) { |
| 227 initialVariableValues.remove(element); | 229 initialVariableValues.remove(element); |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 462 text, | 464 text, |
| 463 constantSystem.createString(new LiteralDartString(text))))]; | 465 constantSystem.createString(new LiteralDartString(text))))]; |
| 464 AstConstant constant = makeConstructedConstant( | 466 AstConstant constant = makeConstructedConstant( |
| 465 compiler, handler, context, node, type, compiler.symbolConstructor, | 467 compiler, handler, context, node, type, compiler.symbolConstructor, |
| 466 CallStructure.ONE_ARG, | 468 CallStructure.ONE_ARG, |
| 467 arguments, arguments); | 469 arguments, arguments); |
| 468 return new AstConstant( | 470 return new AstConstant( |
| 469 context, node, new SymbolConstantExpression(constant.value, text)); | 471 context, node, new SymbolConstantExpression(constant.value, text)); |
| 470 } | 472 } |
| 471 | 473 |
| 472 AstConstant makeTypeConstant(Node node, DartType elementType) { | 474 ConstantExpression makeTypeConstant(DartType elementType) { |
| 473 DartType constantType = | 475 DartType constantType = |
| 474 compiler.backend.typeImplementation.computeType(compiler); | 476 compiler.backend.typeImplementation.computeType(compiler); |
| 475 return new AstConstant( | 477 return new TypeConstantExpression( |
| 476 context, node, new TypeConstantExpression( | 478 new TypeConstantValue(elementType, constantType), elementType); |
| 477 new TypeConstantValue(elementType, constantType), | |
| 478 elementType)); | |
| 479 } | 479 } |
| 480 | 480 |
| 481 /// Returns true if the prefix of the send resolves to a deferred import | 481 /// Returns true if the prefix of the send resolves to a deferred import |
| 482 /// prefix. | 482 /// prefix. |
| 483 bool isDeferredUse(Send send) { | 483 bool isDeferredUse(Send send) { |
| 484 if (send == null) return false; | 484 if (send == null) return false; |
| 485 return compiler.deferredLoadTask | 485 return compiler.deferredLoadTask |
| 486 .deferredPrefixElement(send, elements) != null; | 486 .deferredPrefixElement(send, elements) != null; |
| 487 } | 487 } |
| 488 | 488 |
| 489 AstConstant visitIdentifier(Identifier node) { | 489 AstConstant visitIdentifier(Identifier node) { |
| 490 Element element = elements[node]; | 490 Element element = elements[node]; |
| 491 if (Elements.isClass(element) || Elements.isTypedef(element)) { | 491 if (Elements.isClass(element) || Elements.isTypedef(element)) { |
| 492 TypeDeclarationElement typeDeclarationElement = element; | 492 TypeDeclarationElement typeDeclarationElement = element; |
| 493 DartType type = typeDeclarationElement.rawType; | 493 DartType type = typeDeclarationElement.rawType; |
| 494 return makeTypeConstant(node, type); | 494 return new AstConstant(element, node, makeTypeConstant(type)); |
| 495 } | 495 } |
| 496 return signalNotCompileTimeConstant(node); | 496 return signalNotCompileTimeConstant(node); |
| 497 } | 497 } |
| 498 | 498 |
| 499 // TODO(floitsch): provide better error-messages. | 499 // TODO(floitsch): provide better error-messages. |
| 500 AstConstant visitSend(Send send) { | 500 AstConstant visitSend(Send send) { |
| 501 Element element = elements[send]; | 501 Element element = elements[send]; |
| 502 if (send.isPropertyAccess) { | 502 if (send.isPropertyAccess) { |
| 503 if (isDeferredUse(send)) { | 503 ConstantExpression result; |
| 504 return signalNotCompileTimeConstant(send, | 504 |
| 505 message: MessageKind.DEFERRED_COMPILE_TIME_CONSTANT); | |
| 506 } | |
| 507 if (Elements.isStaticOrTopLevelFunction(element)) { | 505 if (Elements.isStaticOrTopLevelFunction(element)) { |
| 508 FunctionElementX function = element; | 506 FunctionElementX function = element; |
| 509 function.computeType(compiler); | 507 function.computeType(compiler); |
| 510 return new AstConstant( | 508 result = new FunctionConstantExpression( |
| 511 context, send, new FunctionConstantExpression( | 509 new FunctionConstantValue(function), function); |
| 512 new FunctionConstantValue(function), | |
| 513 function)); | |
| 514 } else if (Elements.isStaticOrTopLevelField(element)) { | 510 } else if (Elements.isStaticOrTopLevelField(element)) { |
| 515 ConstantExpression result; | 511 ConstantExpression elementExpression; |
| 516 if (element.isConst) { | 512 if (element.isConst) { |
| 517 result = handler.compileConstant(element); | 513 elementExpression = handler.compileConstant(element); |
| 518 } else if (element.isFinal && !isEvaluatingConstant) { | 514 } else if (element.isFinal && !isEvaluatingConstant) { |
| 519 result = handler.compileVariable(element); | 515 elementExpression = handler.compileVariable(element); |
| 520 } | 516 } |
| 521 if (result != null) { | 517 if (elementExpression != null) { |
| 522 return new AstConstant( | 518 result = |
| 523 context, send, | 519 new VariableConstantExpression(elementExpression.value, element); |
| 524 new VariableConstantExpression(result.value, element)); | |
| 525 } | 520 } |
| 526 } else if (Elements.isClass(element) || Elements.isTypedef(element)) { | 521 } else if (Elements.isClass(element) || Elements.isTypedef(element)) { |
| 527 assert(elements.isTypeLiteral(send)); | 522 assert(elements.isTypeLiteral(send)); |
| 528 return makeTypeConstant(send, elements.getTypeLiteralType(send)); | 523 result = makeTypeConstant(elements.getTypeLiteralType(send)); |
| 529 } else if (send.receiver != null) { | 524 } else if (send.receiver != null) { |
| 530 if (send.selector.asIdentifier().source == "length") { | 525 if (send.selector.asIdentifier().source == "length") { |
| 531 AstConstant left = evaluate(send.receiver); | 526 AstConstant left = evaluate(send.receiver); |
| 532 if (left != null && left.value.isString) { | 527 if (left != null && left.value.isString) { |
| 533 StringConstantValue stringConstantValue = left.value; | 528 StringConstantValue stringConstantValue = left.value; |
| 534 DartString string = stringConstantValue.primitiveValue; | 529 DartString string = stringConstantValue.primitiveValue; |
| 535 IntConstantValue length = constantSystem.createInt(string.length); | 530 IntConstantValue length = constantSystem.createInt(string.length); |
| 536 return new AstConstant( | 531 result = new VariableConstantExpression(length, element); |
| 537 context, send, new VariableConstantExpression(length, element)); | |
| 538 } | 532 } |
| 539 } | 533 } |
| 540 // Fall through to error handling. | 534 // Fall through to error handling. |
| 541 } else if (!Elements.isUnresolved(element) | 535 } else if (!Elements.isUnresolved(element) |
| 542 && element.isVariable | 536 && element.isVariable |
| 543 && element.isConst) { | 537 && element.isConst) { |
| 544 ConstantExpression result = handler.compileConstant(element); | 538 ConstantExpression variableExpression = |
| 545 if (result != null) { | 539 handler.compileConstant(element); |
| 546 return new AstConstant( | 540 if (variableExpression != null) { |
| 547 context, send, | 541 result = new VariableConstantExpression(variableExpression.value, |
| 548 new VariableConstantExpression(result.value, element)); | 542 element); |
| 549 } | 543 } |
| 550 } | 544 } |
| 551 return signalNotCompileTimeConstant(send); | 545 if (result == null) { |
| 546 return signalNotCompileTimeConstant(send); | |
| 547 } | |
| 548 if (isDeferredUse(send)) { | |
| 549 if (isEvaluatingConstant) { | |
| 550 error(send, MessageKind.DEFERRED_COMPILE_TIME_CONSTANT); | |
| 551 } | |
| 552 PrefixElement prefix = compiler.deferredLoadTask | |
| 553 .deferredPrefixElement(send, elements); | |
| 554 result = new DeferredConstantExpression( | |
| 555 new DeferredConstantValue(result.value, prefix), | |
| 556 result, | |
| 557 prefix); | |
| 558 compiler.deferredLoadTask | |
| 559 .registerConstantDeferredUse(result.value, prefix); | |
| 560 } | |
| 561 return new AstConstant(context, send, result); | |
| 552 } else if (send.isCall) { | 562 } else if (send.isCall) { |
| 553 if (element == compiler.identicalFunction | 563 if (element == compiler.identicalFunction |
| 554 && send.argumentCount() == 2) { | 564 && send.argumentCount() == 2) { |
| 555 AstConstant left = evaluate(send.argumentsNode.nodes.head); | 565 AstConstant left = evaluate(send.argumentsNode.nodes.head); |
| 556 AstConstant right = evaluate(send.argumentsNode.nodes.tail.head); | 566 AstConstant right = evaluate(send.argumentsNode.nodes.tail.head); |
| 557 if (left == null || right == null) { | 567 if (left == null || right == null) { |
| 558 return null; | 568 return null; |
| 559 } | 569 } |
| 560 ConstantValue result = | 570 ConstantValue result = |
| 561 constantSystem.identity.fold(left.value, right.value); | 571 constantSystem.identity.fold(left.value, right.value); |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 736 Map<Node, AstConstant> concreteArgumentMap = | 746 Map<Node, AstConstant> concreteArgumentMap = |
| 737 <Node, AstConstant>{}; | 747 <Node, AstConstant>{}; |
| 738 for (Link<Node> link = send.arguments; !link.isEmpty; link = link.tail) { | 748 for (Link<Node> link = send.arguments; !link.isEmpty; link = link.tail) { |
| 739 Node argument = link.head; | 749 Node argument = link.head; |
| 740 NamedArgument namedArgument = argument.asNamedArgument(); | 750 NamedArgument namedArgument = argument.asNamedArgument(); |
| 741 if (namedArgument != null) { | 751 if (namedArgument != null) { |
| 742 argument = namedArgument.expression; | 752 argument = namedArgument.expression; |
| 743 } | 753 } |
| 744 concreteArgumentMap[argument] = evaluateConstant(argument); | 754 concreteArgumentMap[argument] = evaluateConstant(argument); |
| 745 } | 755 } |
| 746 | |
| 747 List<AstConstant> normalizedArguments = | 756 List<AstConstant> normalizedArguments = |
| 748 evaluateArgumentsToConstructor( | 757 evaluateArgumentsToConstructor( |
| 749 node, callStructure, send.arguments, constructor.implementation, | 758 node, callStructure, send.arguments, constructor.implementation, |
| 750 compileArgument: (node) => concreteArgumentMap[node]); | 759 compileArgument: (node) => concreteArgumentMap[node]); |
| 751 List<AstConstant> concreteArguments = | 760 List<AstConstant> concreteArguments = |
| 752 concreteArgumentMap.values.toList(); | 761 concreteArgumentMap.values.toList(); |
| 753 | 762 |
| 754 if (constructor == compiler.intEnvironment || | 763 if (constructor == compiler.intEnvironment || |
| 755 constructor == compiler.boolEnvironment || | 764 constructor == compiler.boolEnvironment || |
| 756 constructor == compiler.stringEnvironment) { | 765 constructor == compiler.stringEnvironment) { |
| (...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1147 ConstantValue get value => expression.value; | 1156 ConstantValue get value => expression.value; |
| 1148 | 1157 |
| 1149 String toString() => expression.toString(); | 1158 String toString() => expression.toString(); |
| 1150 } | 1159 } |
| 1151 | 1160 |
| 1152 /// A synthetic constant used to recover from errors. | 1161 /// A synthetic constant used to recover from errors. |
| 1153 class ErroneousAstConstant extends AstConstant { | 1162 class ErroneousAstConstant extends AstConstant { |
| 1154 ErroneousAstConstant(Element element, Node node) | 1163 ErroneousAstConstant(Element element, Node node) |
| 1155 : super(element, node, new ErroneousConstantExpression()); | 1164 : super(element, node, new ErroneousConstantExpression()); |
| 1156 } | 1165 } |
| OLD | NEW |