| Index: pkg/compiler/lib/src/constants/expressions.dart
|
| diff --git a/pkg/compiler/lib/src/constants/expressions.dart b/pkg/compiler/lib/src/constants/expressions.dart
|
| index f1ad90bfae1106d9e36724eb6c7857f3f068b8a2..0b1d4f1a51cceb0222c5096121759d85b656fddc 100644
|
| --- a/pkg/compiler/lib/src/constants/expressions.dart
|
| +++ b/pkg/compiler/lib/src/constants/expressions.dart
|
| @@ -73,6 +73,9 @@ abstract class ConstantExpression {
|
|
|
| accept(ConstantExpressionVisitor visitor, [context]);
|
|
|
| + /// `true` if this is an erroneous constant expression.
|
| + bool get isErroneous => false;
|
| +
|
| /// Substitute free variables using arguments.
|
| ConstantExpression apply(NormalizedArguments arguments) => this;
|
|
|
| @@ -137,6 +140,9 @@ class ErroneousConstantExpression extends ConstantExpression {
|
|
|
| @override
|
| bool _equals(ErroneousConstantExpression other) => true;
|
| +
|
| + @override
|
| + bool get isErroneous => true;
|
| }
|
|
|
| // TODO(johnniwinther): Avoid the need for this class.
|
| @@ -387,10 +393,28 @@ class MapConstantExpression extends ConstantExpression {
|
| @override
|
| ConstantValue evaluate(Environment environment,
|
| ConstantSystem constantSystem) {
|
| - return constantSystem.createMap(environment.compiler,
|
| + /*return constantSystem.createMap(environment.compiler,
|
| type,
|
| keys.map((k) => k.evaluate(environment, constantSystem)).toList(),
|
| - values.map((v) => v.evaluate(environment, constantSystem)).toList());
|
| + values.map((v) => v.evaluate(environment, constantSystem)).toList());*/
|
| + Map<ConstantValue, ConstantValue> map = <ConstantValue, ConstantValue>{};
|
| +
|
| + for (int i = 0; i < keys.length; i++) {
|
| + ConstantValue key = keys[i].evaluate(environment, constantSystem);
|
| + if (!key.isConstant) {
|
| + return new NonConstantValue();
|
| + }
|
| + ConstantValue value = values[i].evaluate(environment, constantSystem);
|
| + if (!value.isConstant) {
|
| + return new NonConstantValue();
|
| + }
|
| + if (map.containsKey(key)) {
|
| + environment.reportWarning(keys[i], MessageKind.EQUAL_MAP_ENTRY_KEY, {});
|
| + }
|
| + map[key] = value;
|
| + }
|
| + return constantSystem.createMap(
|
| + environment.compiler, type, map.keys.toList(), map.values.toList());
|
| }
|
|
|
| ConstantExpression apply(NormalizedArguments arguments) {
|
| @@ -438,6 +462,8 @@ class ConstructedConstantExpression extends ConstantExpression {
|
| this.arguments) {
|
| assert(type.element == target.enclosingClass);
|
| assert(!arguments.contains(null));
|
| + assert(invariant(NO_LOCATION_SPANNABLE, target.isConst,
|
| + message: "Referenced constructor $target is not constant."));
|
| }
|
|
|
| ConstantExpressionKind get kind => ConstantExpressionKind.CONSTRUCTED;
|
| @@ -447,6 +473,8 @@ class ConstructedConstantExpression extends ConstantExpression {
|
| }
|
|
|
| Map<FieldElement, ConstantExpression> computeInstanceFields() {
|
| + assert(invariant(target, target.constantConstructor != null,
|
| + message: "Constant constructor has not been computed for $target."));
|
| return target.constantConstructor.computeInstanceFields(
|
| arguments, callStructure);
|
| }
|
| @@ -464,13 +492,32 @@ class ConstructedConstantExpression extends ConstantExpression {
|
| @override
|
| ConstantValue evaluate(Environment environment,
|
| ConstantSystem constantSystem) {
|
| - Map<FieldElement, ConstantValue> fieldValues =
|
| - <FieldElement, ConstantValue>{};
|
| - computeInstanceFields().forEach(
|
| - (FieldElement field, ConstantExpression constant) {
|
| - fieldValues[field] = constant.evaluate(environment, constantSystem);
|
| + return environment.evaluateConstructor(target, () {
|
| + Map<FieldElement, ConstantExpression> fieldMap =
|
| + computeInstanceFields();
|
| + if (fieldMap == null) {
|
| + // An erroneous constant constructor was encountered in the super-chain.
|
| + return new NonConstantValue();
|
| + }
|
| + bool isValidAsConstant = true;
|
| + Map<FieldElement, ConstantValue> fieldValues =
|
| + <FieldElement, ConstantValue>{};
|
| + fieldMap.forEach((FieldElement field, ConstantExpression constant) {
|
| + ConstantValue value = constant.evaluate(environment, constantSystem);
|
| + assert(invariant(CURRENT_ELEMENT_SPANNABLE, value != null,
|
| + message: "No value computed for ${constant.getText()}."));
|
| + if (value.isConstant) {
|
| + fieldValues[field] = value;
|
| + } else {
|
| + isValidAsConstant = false;
|
| + }
|
| + });
|
| + if (isValidAsConstant) {
|
| + return new ConstructedConstantValue(computeInstanceType(), fieldValues);
|
| + } else {
|
| + return new NonConstantValue();
|
| + }
|
| });
|
| - return new ConstructedConstantValue(computeInstanceType(), fieldValues);
|
| }
|
|
|
| @override
|
| @@ -517,11 +564,15 @@ class ConcatenateConstantExpression extends ConstantExpression {
|
| @override
|
| ConstantValue evaluate(Environment environment,
|
| ConstantSystem constantSystem) {
|
| + bool isValidAsConstant = true;
|
| DartString accumulator;
|
| for (ConstantExpression expression in expressions) {
|
| ConstantValue value = expression.evaluate(environment, constantSystem);
|
| DartString valueString;
|
| - if (value.isNum || value.isBool) {
|
| + if (!value.isConstant) {
|
| + isValidAsConstant = false;
|
| + continue;
|
| + } else if (value.isNum || value.isBool) {
|
| PrimitiveConstantValue primitive = value;
|
| valueString =
|
| new DartString.literal(primitive.primitiveValue.toString());
|
| @@ -531,7 +582,13 @@ class ConcatenateConstantExpression extends ConstantExpression {
|
| } else {
|
| // TODO(johnniwinther): Specialize message to indicated that the problem
|
| // is not constness but the types of the const expressions.
|
| - return new NonConstantValue();
|
| + environment.reportError(
|
| + expression,
|
| + MessageKind.INVALID_CONSTANT_INTERPOLATION_TYPE,
|
| + {'constant': expression,
|
| + 'type': value.getType(environment.coreTypes)});
|
| + isValidAsConstant = false;
|
| + continue;
|
| }
|
| if (accumulator == null) {
|
| accumulator = valueString;
|
| @@ -539,7 +596,10 @@ class ConcatenateConstantExpression extends ConstantExpression {
|
| accumulator = new DartString.concat(accumulator, valueString);
|
| }
|
| }
|
| - return constantSystem.createString(accumulator);
|
| + if (isValidAsConstant) {
|
| + return constantSystem.createString(accumulator);
|
| + }
|
| + return new NonConstantValue();
|
| }
|
|
|
| @override
|
| @@ -587,8 +647,7 @@ class SymbolConstantExpression extends ConstantExpression {
|
| @override
|
| ConstantValue evaluate(Environment environment,
|
| ConstantSystem constantSystem) {
|
| - // TODO(johnniwinther): Implement this.
|
| - throw new UnsupportedError('SymbolConstantExpression.evaluate');
|
| + return constantSystem.createSymbol(environment.compiler, name);
|
| }
|
|
|
| @override
|
| @@ -632,7 +691,10 @@ class TypeConstantExpression extends ConstantExpression {
|
| class VariableConstantExpression extends ConstantExpression {
|
| final VariableElement element;
|
|
|
| - VariableConstantExpression(this.element);
|
| + VariableConstantExpression(this.element) {
|
| + /*assert(invariant(NO_LOCATION_SPANNABLE, element.isConst,
|
| + message: "Referenced variable $element is not constant."));*/
|
| + }
|
|
|
| ConstantExpressionKind get kind => ConstantExpressionKind.VARIABLE;
|
|
|
| @@ -643,7 +705,9 @@ class VariableConstantExpression extends ConstantExpression {
|
| @override
|
| ConstantValue evaluate(Environment environment,
|
| ConstantSystem constantSystem) {
|
| - return element.constant.evaluate(environment, constantSystem);
|
| + return environment.evaluateVariable(element, () {
|
| + return element.constant.evaluate(environment, constantSystem);
|
| + });
|
| }
|
|
|
| @override
|
| @@ -704,9 +768,29 @@ class BinaryConstantExpression extends ConstantExpression {
|
| @override
|
| ConstantValue evaluate(Environment environment,
|
| ConstantSystem constantSystem) {
|
| - return constantSystem.lookupBinary(operator).fold(
|
| - left.evaluate(environment, constantSystem),
|
| - right.evaluate(environment, constantSystem));
|
| + ConstantValue leftValue = left.evaluate(environment, constantSystem);
|
| + ConstantValue rightValue = right.evaluate(environment, constantSystem);
|
| + if (!leftValue.isConstant ||
|
| + !rightValue.isConstant) {
|
| + return new NonConstantValue();
|
| + }
|
| + ConstantExpressionChecker checker =
|
| + new ConstantExpressionChecker(environment);
|
| + bool isValid = checker.checkBinaryExpression(
|
| + this,
|
| + checker.createInfo(left, leftValue),
|
| + operator,
|
| + checker.createInfo(right, rightValue));
|
| +
|
| + BinaryOperation operation = constantSystem.lookupBinary(operator);
|
| + assert(invariant(NO_LOCATION_SPANNABLE, operation != null,
|
| + message: "No binary operation for $operator."));
|
| + ConstantValue value = operation.fold(leftValue, rightValue);
|
| + if (value != null) {
|
| + return value;
|
| + }
|
| + assert(!isValid);
|
| + return new NonConstantValue();
|
| }
|
|
|
| ConstantExpression apply(NormalizedArguments arguments) {
|
| @@ -730,26 +814,32 @@ class BinaryConstantExpression extends ConstantExpression {
|
| case BinaryOperatorKind.LTEQ:
|
| return coreTypes.boolType;
|
| case BinaryOperatorKind.ADD:
|
| - if (knownLeftType == coreTypes.stringType) {
|
| - assert(knownRightType == coreTypes.stringType);
|
| + if (knownLeftType == coreTypes.stringType &&
|
| + knownRightType == coreTypes.stringType) {
|
| return coreTypes.stringType;
|
| } else if (knownLeftType == coreTypes.intType &&
|
| knownRightType == coreTypes.intType) {
|
| return coreTypes.intType;
|
| + } else if ((knownLeftType == coreTypes.intType ||
|
| + knownLeftType == coreTypes.doubleType) &&
|
| + (knownRightType == coreTypes.intType ||
|
| + knownRightType == coreTypes.doubleType)) {
|
| + return coreTypes.doubleType;
|
| }
|
| - assert(knownLeftType == coreTypes.doubleType ||
|
| - knownRightType == coreTypes.doubleType);
|
| - return coreTypes.doubleType;
|
| + return null;
|
| case BinaryOperatorKind.SUB:
|
| case BinaryOperatorKind.MUL:
|
| case BinaryOperatorKind.MOD:
|
| if (knownLeftType == coreTypes.intType &&
|
| knownRightType == coreTypes.intType) {
|
| return coreTypes.intType;
|
| + } else if ((knownLeftType == coreTypes.intType ||
|
| + knownLeftType == coreTypes.doubleType) &&
|
| + (knownRightType == coreTypes.intType ||
|
| + knownRightType == coreTypes.doubleType)) {
|
| + return coreTypes.doubleType;
|
| }
|
| - assert(knownLeftType == coreTypes.doubleType ||
|
| - knownRightType == coreTypes.doubleType);
|
| - return coreTypes.doubleType;
|
| + return null;
|
| case BinaryOperatorKind.DIV:
|
| return coreTypes.doubleType;
|
| case BinaryOperatorKind.IDIV:
|
| @@ -767,7 +857,6 @@ class BinaryConstantExpression extends ConstantExpression {
|
| }
|
| }
|
|
|
| -
|
| int get precedence => PRECEDENCE_MAP[operator.kind];
|
|
|
| @override
|
| @@ -823,9 +912,12 @@ class IdenticalConstantExpression extends ConstantExpression {
|
| @override
|
| ConstantValue evaluate(Environment environment,
|
| ConstantSystem constantSystem) {
|
| - return constantSystem.identity.fold(
|
| - left.evaluate(environment, constantSystem),
|
| - right.evaluate(environment, constantSystem));
|
| + ConstantValue leftValue = left.evaluate(environment, constantSystem);
|
| + ConstantValue rightValue = right.evaluate(environment, constantSystem);
|
| + if (leftValue.isConstant && rightValue.isConstant) {
|
| + return constantSystem.identity.fold(leftValue, rightValue);
|
| + }
|
| + return new NonConstantValue();
|
| }
|
|
|
| ConstantExpression apply(NormalizedArguments arguments) {
|
| @@ -870,8 +962,16 @@ class UnaryConstantExpression extends ConstantExpression {
|
| @override
|
| ConstantValue evaluate(Environment environment,
|
| ConstantSystem constantSystem) {
|
| - return constantSystem.lookupUnary(operator).fold(
|
| - expression.evaluate(environment, constantSystem));
|
| + ConstantValue expressionValue =
|
| + expression.evaluate(environment, constantSystem);
|
| + ConstantExpressionChecker checker =
|
| + new ConstantExpressionChecker(environment);
|
| + bool isValidAsConstant = checker.checkUnary(
|
| + operator, checker.createInfo(expression, expressionValue));
|
| + if (isValidAsConstant) {
|
| + return constantSystem.lookupUnary(operator).fold(expressionValue);
|
| + }
|
| + return new NonConstantValue();
|
| }
|
|
|
| ConstantExpression apply(NormalizedArguments arguments) {
|
| @@ -998,12 +1098,17 @@ class ConditionalConstantExpression extends ConstantExpression {
|
| trueExp.evaluate(environment, constantSystem);
|
| ConstantValue falseValue =
|
| falseExp.evaluate(environment, constantSystem);
|
| - if (conditionValue.isTrue) {
|
| + ConstantExpressionChecker checker =
|
| + new ConstantExpressionChecker(environment);
|
| + bool isValidAsConstant = checker.checkConditional(
|
| + checker.createInfo(condition, conditionValue));
|
| + if (!isValidAsConstant) {
|
| + return new NonConstantValue();
|
| + } else if (conditionValue.isTrue) {
|
| return trueValue;
|
| - } else if (conditionValue.isFalse) {
|
| - return falseValue;
|
| } else {
|
| - return new NonConstantValue();
|
| + assert(conditionValue.isFalse);
|
| + return falseValue;
|
| }
|
| }
|
|
|
| @@ -1128,7 +1233,12 @@ class BoolFromEnvironmentConstantExpression
|
| } else {
|
| defaultConstantValue = constantSystem.createBool(false);
|
| }
|
| - if (!nameConstantValue.isString) {
|
| + ConstantExpressionChecker checker =
|
| + new ConstantExpressionChecker(environment);
|
| + bool isValidAsConstant = checker.checkBoolFromEnvironment(
|
| + checker.createInfo(name, nameConstantValue),
|
| + checker.createInfo(defaultValue, defaultConstantValue));
|
| + if (!isValidAsConstant) {
|
| return new NonConstantValue();
|
| }
|
| StringConstantValue nameStringConstantValue = nameConstantValue;
|
| @@ -1182,7 +1292,12 @@ class IntFromEnvironmentConstantExpression
|
| } else {
|
| defaultConstantValue = constantSystem.createNull();
|
| }
|
| - if (!nameConstantValue.isString) {
|
| + ConstantExpressionChecker checker =
|
| + new ConstantExpressionChecker(environment);
|
| + bool isValidAsConstant = checker.checkIntFromEnvironment(
|
| + checker.createInfo(name, nameConstantValue),
|
| + checker.createInfo(defaultValue, defaultConstantValue));
|
| + if (!isValidAsConstant) {
|
| return new NonConstantValue();
|
| }
|
| StringConstantValue nameStringConstantValue = nameConstantValue;
|
| @@ -1238,7 +1353,12 @@ class StringFromEnvironmentConstantExpression
|
| } else {
|
| defaultConstantValue = constantSystem.createNull();
|
| }
|
| - if (!nameConstantValue.isString) {
|
| + ConstantExpressionChecker checker =
|
| + new ConstantExpressionChecker(environment);
|
| + bool isValidAsConstant = checker.checkStringFromEnvironment(
|
| + checker.createInfo(name, nameConstantValue),
|
| + checker.createInfo(defaultValue, defaultConstantValue));
|
| + if (!isValidAsConstant) {
|
| return new NonConstantValue();
|
| }
|
| StringConstantValue nameStringConstantValue = nameConstantValue;
|
| @@ -1605,4 +1725,4 @@ class ConstExpPrinter extends ConstantExpressionVisitor {
|
| }
|
|
|
| String toString() => sb.toString();
|
| -}
|
| +}
|
|
|