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..1c066ed2c0485add0ec9bd279654610dc58306a5 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) { |
+ 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(); |
} |