Chromium Code Reviews| 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 71962e88957bcc163fdc0d7df455753022b6ab8c..92b193d192a120514afcf42acb7200bae756acc9 100644 |
| --- a/pkg/compiler/lib/src/compile_time_constants.dart |
| +++ b/pkg/compiler/lib/src/compile_time_constants.dart |
| @@ -414,7 +414,10 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> { |
| AstConstant evaluate(Node node) { |
| // TODO(johnniwinther): should there be a visitErrorNode? |
| if (node is ErrorNode) return new ErroneousAstConstant(context, node); |
| - return node.accept(this); |
| + AstConstant result = node.accept(this); |
| + assert(invariant(node, !isEvaluatingConstant || result != null, |
| + message: "No AstConstant computed for the node.")); |
| + return result; |
| } |
| AstConstant evaluateConstant(Node node) { |
| @@ -422,7 +425,8 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> { |
| isEvaluatingConstant = true; |
| AstConstant result = node.accept(this); |
| isEvaluatingConstant = oldIsEvaluatingConstant; |
| - assert(result != null); |
| + assert(invariant(node, result != null, |
| + message: "No AstConstant computed for the node.")); |
| return result; |
| } |
| @@ -461,8 +465,8 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> { |
| !link.isEmpty; |
| link = link.tail) { |
| AstConstant argument = evaluateConstant(link.head); |
| - if (argument == null) { |
| - return null; |
| + if (argument == null || argument.isError) { |
| + return argument; |
| } |
| argumentExpressions.add(argument.expression); |
| argumentValues.add(argument.value); |
| @@ -488,12 +492,12 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> { |
| link = link.tail) { |
| LiteralMapEntry entry = link.head; |
| AstConstant key = evaluateConstant(entry.key); |
| - if (key == null) { |
| - return null; |
| + if (key == null || key.isError) { |
| + return key; |
| } |
| AstConstant value = evaluateConstant(entry.value); |
| - if (value == null) { |
| - return null; |
| + if (value == null || value.isError) { |
| + return value; |
| } |
| if (!map.containsKey(key.value)) { |
| keyValues.add(key.value); |
| @@ -530,7 +534,12 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> { |
| AstConstant visitStringJuxtaposition(StringJuxtaposition node) { |
| AstConstant left = evaluate(node.first); |
| AstConstant right = evaluate(node.second); |
| - if (left == null || right == null) return null; |
| + if (left == null || left.isError) { |
| + return left; |
| + } |
| + if (right == null || right.isError) { |
| + return right; |
| + } |
| StringConstantValue leftValue = left.value; |
| StringConstantValue rightValue = right.value; |
| return new AstConstant( |
| @@ -544,16 +553,16 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> { |
| AstConstant visitStringInterpolation(StringInterpolation node) { |
| List<ConstantExpression> subexpressions = <ConstantExpression>[]; |
| AstConstant initialString = evaluate(node.string); |
| - if (initialString == null) { |
| - return null; |
| + if (initialString == null || initialString.isError) { |
| + return initialString; |
| } |
| subexpressions.add(initialString.expression); |
| StringConstantValue initialStringValue = initialString.value; |
| DartString accumulator = initialStringValue.primitiveValue; |
| for (StringInterpolationPart part in node.parts) { |
| AstConstant subexpression = evaluate(part.expression); |
| - if (subexpression == null) { |
| - return null; |
| + if (subexpression == null || subexpression.isError) { |
| + return subexpression; |
| } |
| subexpressions.add(subexpression.expression); |
| ConstantValue expression = subexpression.value; |
| @@ -578,7 +587,6 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> { |
| accumulator = |
| new DartString.concat(accumulator, partStringValue.primitiveValue); |
| } |
| - ; |
| return new AstConstant( |
| context, |
| node, |
| @@ -725,8 +733,8 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> { |
| } else if (send.isPrefix) { |
| assert(send.isOperator); |
| AstConstant receiverConstant = evaluate(send.receiver); |
| - if (receiverConstant == null) { |
| - return null; |
| + if (receiverConstant == null && receiverConstant.isError) { |
|
Harry Terkelsen
2016/06/30 16:39:03
should be ||
Johnni Winther
2016/07/01 08:18:03
Thanks!
|
| + return receiverConstant; |
| } |
| Operator node = send.selector; |
| UnaryOperator operator = UnaryOperator.parse(node.source); |
| @@ -747,8 +755,11 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> { |
| assert(send.argumentCount() == 1); |
| AstConstant left = evaluate(send.receiver); |
| AstConstant right = evaluate(send.argumentsNode.nodes.head); |
| - if (left == null || right == null) { |
| - return null; |
| + if (left == null || left.isError) { |
| + return left; |
| + } |
| + if (right == null || right.isError) { |
| + return right; |
| } |
| ConstantValue leftValue = left.value; |
| ConstantValue rightValue = right.value; |
| @@ -796,8 +807,8 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> { |
| AstConstant visitConditional(Conditional node) { |
| AstConstant condition = evaluate(node.condition); |
| - if (condition == null) { |
| - return null; |
| + if (condition == null || condition.isError) { |
| + return condition; |
| } else if (!condition.value.isBool) { |
| DartType conditionType = condition.value.getType(coreTypes); |
| if (isEvaluatingConstant) { |
| @@ -809,8 +820,11 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> { |
| } |
| AstConstant thenExpression = evaluate(node.thenExpression); |
| AstConstant elseExpression = evaluate(node.elseExpression); |
| - if (thenExpression == null || elseExpression == null) { |
| - return null; |
| + if (thenExpression == null || thenExpression.isError) { |
| + return thenExpression; |
| + } |
| + if (elseExpression == null || elseExpression.isError) { |
| + return elseExpression; |
| } |
| BoolConstantValue boolCondition = condition.value; |
| return new AstConstant( |
| @@ -978,48 +992,43 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> { |
| ConstantValue defaultValue = normalizedArguments[1].value; |
| if (firstArgument.isNull) { |
| - reporter.reportErrorMessage( |
| + return reportNotCompileTimeConstant( |
| normalizedArguments[0].node, MessageKind.NULL_NOT_ALLOWED); |
| - return null; |
| } |
| if (!firstArgument.isString) { |
| DartType type = defaultValue.getType(coreTypes); |
| - reporter.reportErrorMessage( |
| + return reportNotCompileTimeConstant( |
| normalizedArguments[0].node, |
| MessageKind.NOT_ASSIGNABLE, |
| {'fromType': type, 'toType': coreTypes.stringType}); |
| - return null; |
| } |
| if (constructor.isIntFromEnvironmentConstructor && |
| !(defaultValue.isNull || defaultValue.isInt)) { |
| DartType type = defaultValue.getType(coreTypes); |
| - reporter.reportErrorMessage( |
| + return reportNotCompileTimeConstant( |
| normalizedArguments[1].node, |
| MessageKind.NOT_ASSIGNABLE, |
| {'fromType': type, 'toType': coreTypes.intType}); |
| - return null; |
| } |
| if (constructor.isBoolFromEnvironmentConstructor && |
| !(defaultValue.isNull || defaultValue.isBool)) { |
| DartType type = defaultValue.getType(coreTypes); |
| - reporter.reportErrorMessage( |
| + return reportNotCompileTimeConstant( |
| normalizedArguments[1].node, |
| MessageKind.NOT_ASSIGNABLE, |
| {'fromType': type, 'toType': coreTypes.boolType}); |
| - return null; |
| } |
| if (constructor.isStringFromEnvironmentConstructor && |
| !(defaultValue.isNull || defaultValue.isString)) { |
| DartType type = defaultValue.getType(coreTypes); |
| - reporter.reportErrorMessage( |
| + return reportNotCompileTimeConstant( |
| normalizedArguments[1].node, |
| MessageKind.NOT_ASSIGNABLE, |
| {'fromType': type, 'toType': coreTypes.stringType}); |
| - return null; |
| } |
| String name = firstArgument.primitiveValue.slowToString(); |
| @@ -1103,6 +1112,11 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> { |
| fieldConstants.forEach((FieldElement field, AstConstant astConstant) { |
| fieldValues[field] = astConstant.value; |
| }); |
| + for (AstConstant fieldValue in fieldConstants.values) { |
| + if (fieldValue.isError) { |
| + return fieldValue; |
| + } |
| + } |
| return new AstConstant( |
| context, |
| node, |
| @@ -1115,13 +1129,18 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> { |
| return node.expression.accept(this); |
| } |
| + AstConstant reportNotCompileTimeConstant(Node node, MessageKind message, |
| + [Map arguments = const {}]) { |
| + reporter.reportErrorMessage(node, message, arguments); |
| + return new AstConstant(context, node, new ErroneousConstantExpression(), |
| + new NullConstantValue()); |
| + } |
| + |
| AstConstant signalNotCompileTimeConstant(Node node, |
| - {MessageKind message: MessageKind.NOT_A_COMPILE_TIME_CONSTANT}) { |
| + {MessageKind message: MessageKind.NOT_A_COMPILE_TIME_CONSTANT, |
| + Map arguments: const {}}) { |
| if (isEvaluatingConstant) { |
| - reporter.reportErrorMessage(node, message); |
| - |
| - return new AstConstant(context, node, new ErroneousConstantExpression(), |
| - new NullConstantValue()); |
| + return reportNotCompileTimeConstant(node, message, arguments); |
| } |
| // Else we don't need to do anything. The final handler is only |
| // optimistically trying to compile constants. So it is normal that we |
| @@ -1372,6 +1391,8 @@ class AstConstant { |
| value); |
| } |
| + bool get isError => expression.kind == ConstantExpressionKind.ERRONEOUS; |
| + |
| String toString() => expression.toString(); |
| } |