| Index: pkg/compiler/lib/src/compile_time_constants.dart
|
| diff --git a/pkg/compiler/lib/src/compile_time_constants.dart b/pkg/compiler/lib/src/compile_time_constants.dart
|
| index c16a09ceba8378ce060892a619fe6d0c31164acc..a320b23f83c538838a5f9a77f61016c6b92297e4 100644
|
| --- a/pkg/compiler/lib/src/compile_time_constants.dart
|
| +++ b/pkg/compiler/lib/src/compile_time_constants.dart
|
| @@ -41,14 +41,21 @@ abstract class ConstantCompiler extends ConstantEnvironment {
|
| /// if possible.
|
| void compileVariable(VariableElement element);
|
|
|
| - /// Compiles the compile-time constant for [node], or reports an error if
|
| - /// [node] is not a compile-time constant.
|
| + /// Compiles the constant for [node].
|
| + ///
|
| + /// Reports an error if [node] is not a compile-time constant and
|
| + /// [enforceConst].
|
| + ///
|
| + /// If `!enforceConst`, then if [node] is a "runtime constant" (for example
|
| + /// a reference to a deferred constant) it will be returned - otherwise null
|
| + /// is returned.
|
| ///
|
| /// Depending on implementation, the constant compiler might also compute
|
| - /// the compile-time constant for the backend interpretation of constants.
|
| + /// the constant for the backend interpretation of constants.
|
| ///
|
| /// The returned constant is always of the frontend interpretation.
|
| - ConstantExpression compileNode(Node node, TreeElements elements);
|
| + ConstantExpression compileNode(Node node, TreeElements elements,
|
| + {bool enforceConst: true});
|
|
|
| /// Compiles the compile-time constant for the value [metadata], or reports an
|
| /// error if the value is not a compile-time constant.
|
| @@ -213,8 +220,9 @@ abstract class ConstantCompilerBase implements ConstantCompiler {
|
| return constant != null ? constant.expression : null;
|
| }
|
|
|
| - ConstantExpression compileNode(Node node, TreeElements elements) {
|
| - return compileNodeWithDefinitions(node, elements);
|
| + ConstantExpression compileNode(Node node, TreeElements elements,
|
| + {bool enforceConst: true}) {
|
| + return compileNodeWithDefinitions(node, elements, isConst: enforceConst);
|
| }
|
|
|
| ConstantExpression compileMetadata(MetadataAnnotation metadata,
|
| @@ -469,13 +477,11 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| context, node, new SymbolConstantExpression(constant.value, text));
|
| }
|
|
|
| - AstConstant makeTypeConstant(Node node, DartType elementType) {
|
| + ConstantExpression makeTypeConstant(DartType elementType) {
|
| DartType constantType =
|
| compiler.backend.typeImplementation.computeType(compiler);
|
| - return new AstConstant(
|
| - context, node, new TypeConstantExpression(
|
| - new TypeConstantValue(elementType, constantType),
|
| - elementType));
|
| + return new TypeConstantExpression(
|
| + new TypeConstantValue(elementType, constantType), elementType);
|
| }
|
|
|
| /// Returns true if the prefix of the send resolves to a deferred import
|
| @@ -491,7 +497,7 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| if (Elements.isClass(element) || Elements.isTypedef(element)) {
|
| TypeDeclarationElement typeDeclarationElement = element;
|
| DartType type = typeDeclarationElement.rawType;
|
| - return makeTypeConstant(node, type);
|
| + return new AstConstant(element, node, makeTypeConstant(type));
|
| }
|
| return signalNotCompileTimeConstant(node);
|
| }
|
| @@ -500,32 +506,27 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| AstConstant visitSend(Send send) {
|
| Element element = elements[send];
|
| if (send.isPropertyAccess) {
|
| - if (isDeferredUse(send)) {
|
| - return signalNotCompileTimeConstant(send,
|
| - message: MessageKind.DEFERRED_COMPILE_TIME_CONSTANT);
|
| - }
|
| + ConstantExpression result;
|
| +
|
| if (Elements.isStaticOrTopLevelFunction(element)) {
|
| FunctionElementX function = element;
|
| function.computeType(compiler);
|
| - return new AstConstant(
|
| - context, send, new FunctionConstantExpression(
|
| - new FunctionConstantValue(function),
|
| - function));
|
| + result = new FunctionConstantExpression(
|
| + new FunctionConstantValue(function), function);
|
| } else if (Elements.isStaticOrTopLevelField(element)) {
|
| - ConstantExpression result;
|
| + ConstantExpression elementExpression;
|
| if (element.isConst) {
|
| - result = handler.compileConstant(element);
|
| + elementExpression = handler.compileConstant(element);
|
| } else if (element.isFinal && !isEvaluatingConstant) {
|
| - result = handler.compileVariable(element);
|
| + elementExpression = handler.compileVariable(element);
|
| }
|
| - if (result != null) {
|
| - return new AstConstant(
|
| - context, send,
|
| - new VariableConstantExpression(result.value, element));
|
| + if (elementExpression != null) {
|
| + result =
|
| + new VariableConstantExpression(elementExpression.value, element);
|
| }
|
| } else if (Elements.isClass(element) || Elements.isTypedef(element)) {
|
| assert(elements.isTypeLiteral(send));
|
| - return makeTypeConstant(send, elements.getTypeLiteralType(send));
|
| + result = makeTypeConstant(elements.getTypeLiteralType(send));
|
| } else if (send.receiver != null) {
|
| if (send.selector.asIdentifier().source == "length") {
|
| AstConstant left = evaluate(send.receiver);
|
| @@ -533,22 +534,37 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| StringConstantValue stringConstantValue = left.value;
|
| DartString string = stringConstantValue.primitiveValue;
|
| IntConstantValue length = constantSystem.createInt(string.length);
|
| - return new AstConstant(
|
| - context, send, new VariableConstantExpression(length, element));
|
| + result = new VariableConstantExpression(length, element);
|
| }
|
| }
|
| // Fall through to error handling.
|
| } else if (!Elements.isUnresolved(element)
|
| && element.isVariable
|
| && element.isConst) {
|
| - ConstantExpression result = handler.compileConstant(element);
|
| - if (result != null) {
|
| - return new AstConstant(
|
| - context, send,
|
| - new VariableConstantExpression(result.value, element));
|
| + ConstantExpression variableExpression =
|
| + handler.compileConstant(element);
|
| + if (variableExpression != null) {
|
| + result = new VariableConstantExpression(variableExpression.value,
|
| + element);
|
| }
|
| }
|
| - return signalNotCompileTimeConstant(send);
|
| + if (result == null) {
|
| + return signalNotCompileTimeConstant(send);
|
| + }
|
| + if (isDeferredUse(send)) {
|
| + if (isEvaluatingConstant) {
|
| + error(send, MessageKind.DEFERRED_COMPILE_TIME_CONSTANT);
|
| + }
|
| + PrefixElement prefix = compiler.deferredLoadTask
|
| + .deferredPrefixElement(send, elements);
|
| + result = new DeferredConstantExpression(
|
| + new DeferredConstantValue(result.value, prefix),
|
| + result,
|
| + prefix);
|
| + compiler.deferredLoadTask
|
| + .registerConstantDeferredUse(result.value, prefix);
|
| + }
|
| + return new AstConstant(context, send, result);
|
| } else if (send.isCall) {
|
| if (element == compiler.identicalFunction
|
| && send.argumentCount() == 2) {
|
| @@ -743,7 +759,6 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| }
|
| concreteArgumentMap[argument] = evaluateConstant(argument);
|
| }
|
| -
|
| List<AstConstant> normalizedArguments =
|
| evaluateArgumentsToConstructor(
|
| node, callStructure, send.arguments, constructor.implementation,
|
|
|