| 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 f5876d8d495fc08127bbaec7def20f9fc9333615..a1c37688a01b33dd4361e689ec7eab00fda1fd89 100644
|
| --- a/pkg/compiler/lib/src/compile_time_constants.dart
|
| +++ b/pkg/compiler/lib/src/compile_time_constants.dart
|
| @@ -22,6 +22,16 @@ import 'universe/universe.dart' show CallStructure;
|
| /// A [ConstantEnvironment] provides access for constants compiled for variable
|
| /// initializers.
|
| abstract class ConstantEnvironment {
|
| + /// The [ConstantSystem] used by this environment.
|
| + ConstantSystem get constantSystem;
|
| +
|
| + /// Returns the constant value computed for [expression].
|
| + // TODO(johnniwinther): Support directly evaluation of [expression].
|
| + ConstantValue getConstantValue(ConstantExpression expression);
|
| +
|
| + /// Returns the constant value for the initializer of [element].
|
| + ConstantValue getConstantValueForVariable(VariableElement element);
|
| +
|
| /// Returns the constant for the initializer of [element].
|
| ConstantExpression getConstantForVariable(VariableElement element);
|
| }
|
| @@ -73,13 +83,18 @@ abstract class ConstantCompiler extends ConstantEnvironment {
|
| /// A [BackendConstantEnvironment] provides access to constants needed for
|
| /// backend implementation.
|
| abstract class BackendConstantEnvironment extends ConstantEnvironment {
|
| + /// Returns the compile-time constant value associated with [node].
|
| + ///
|
| + /// Depending on implementation, the constant might be stored in [elements].
|
| + ConstantValue getConstantValueForNode(Node node, TreeElements elements);
|
| +
|
| /// Returns the compile-time constant associated with [node].
|
| ///
|
| /// Depending on implementation, the constant might be stored in [elements].
|
| ConstantExpression getConstantForNode(Node node, TreeElements elements);
|
|
|
| /// Returns the compile-time constant value of [metadata].
|
| - ConstantExpression getConstantForMetadata(MetadataAnnotation metadata);
|
| + ConstantValue getConstantValueForMetadata(MetadataAnnotation metadata);
|
| }
|
|
|
| /// Interface for the task that compiles the constant environments for the
|
| @@ -87,6 +102,13 @@ abstract class BackendConstantEnvironment extends ConstantEnvironment {
|
| abstract class ConstantCompilerTask extends CompilerTask
|
| implements ConstantCompiler {
|
| ConstantCompilerTask(Compiler compiler) : super(compiler);
|
| +
|
| + /// Copy all cached constant values from [task].
|
| + ///
|
| + /// This is a hack to support reuse cached compilers in memory_compiler.
|
| + // TODO(johnniwinther): Remove this when values are computed from the
|
| + // expressions.
|
| + void copyConstantValues(ConstantCompilerTask task);
|
| }
|
|
|
| /**
|
| @@ -117,8 +139,17 @@ abstract class ConstantCompilerBase implements ConstantCompiler {
|
| /** The set of variable elements that are in the process of being computed. */
|
| final Set<VariableElement> pendingVariables = new Set<VariableElement>();
|
|
|
| + final Map<ConstantExpression, ConstantValue> constantValueMap =
|
| + <ConstantExpression, ConstantValue>{};
|
| +
|
| ConstantCompilerBase(this.compiler, this.constantSystem);
|
|
|
| + @override
|
| + ConstantValue getConstantValueForVariable(VariableElement element) {
|
| + return getConstantValue(initialVariableValues[element.declaration]);
|
| + }
|
| +
|
| + @override
|
| ConstantExpression getConstantForVariable(VariableElement element) {
|
| return initialVariableValues[element.declaration];
|
| }
|
| @@ -159,35 +190,39 @@ abstract class ConstantCompilerBase implements ConstantCompiler {
|
| if (isConst) {
|
| compiler.reportError(
|
| node, MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS);
|
| - return new ErroneousConstantExpression();
|
| + ConstantExpression expression = new ErroneousConstantExpression();
|
| + constantValueMap[expression] = constantSystem.createNull();
|
| + return expression;
|
| }
|
| return null;
|
| }
|
| pendingVariables.add(element);
|
|
|
| Expression initializer = element.initializer;
|
| - ConstantExpression value;
|
| + ConstantExpression expression;
|
| if (initializer == null) {
|
| // No initial value.
|
| - value = new NullConstantExpression(new NullConstantValue());
|
| + expression = new NullConstantExpression();
|
| + constantValueMap[expression] = constantSystem.createNull();
|
| } else {
|
| - value = compileNodeWithDefinitions(
|
| + expression = compileNodeWithDefinitions(
|
| initializer, definitions, isConst: isConst);
|
| if (compiler.enableTypeAssertions &&
|
| - value != null &&
|
| + expression != null &&
|
| element.isField) {
|
| DartType elementType = element.type;
|
| - if (elementType.isMalformed && !value.value.isNull) {
|
| + ConstantValue value = getConstantValue(expression);
|
| + if (elementType.isMalformed && !value.isNull) {
|
| if (isConst) {
|
| ErroneousElement element = elementType.element;
|
| compiler.reportError(
|
| node, element.messageKind, element.messageArguments);
|
| } else {
|
| // We need to throw an exception at runtime.
|
| - value = null;
|
| + expression = null;
|
| }
|
| } else {
|
| - DartType constantType = value.value.getType(compiler.coreTypes);
|
| + DartType constantType = value.getType(compiler.coreTypes);
|
| if (!constantSystem.isSubtype(compiler.types,
|
| constantType, elementType)) {
|
| if (isConst) {
|
| @@ -197,20 +232,20 @@ abstract class ConstantCompilerBase implements ConstantCompiler {
|
| } else {
|
| // If the field cannot be lazily initialized, we will throw
|
| // the exception at runtime.
|
| - value = null;
|
| + expression = null;
|
| }
|
| }
|
| }
|
| }
|
| }
|
| - if (value != null) {
|
| - initialVariableValues[element.declaration] = value;
|
| + if (expression != null) {
|
| + initialVariableValues[element.declaration] = expression;
|
| } else {
|
| assert(invariant(element, !isConst,
|
| message: "Variable $element does not compile to a constant."));
|
| }
|
| pendingVariables.remove(element);
|
| - return value;
|
| + return expression;
|
| }
|
|
|
| ConstantExpression compileNodeWithDefinitions(Node node,
|
| @@ -220,7 +255,15 @@ abstract class ConstantCompilerBase implements ConstantCompiler {
|
| CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator(
|
| this, definitions, compiler, isConst: isConst);
|
| AstConstant constant = evaluator.evaluate(node);
|
| - return constant != null ? constant.expression : null;
|
| + if (constant != null) {
|
| + constantValueMap[constant.expression] = constant.value;
|
| + return constant.expression;
|
| + }
|
| + return null;
|
| + }
|
| +
|
| + ConstantValue getConstantValue(ConstantExpression expression) {
|
| + return constantValueMap[expression];
|
| }
|
|
|
| ConstantExpression compileNode(Node node, TreeElements elements,
|
| @@ -255,10 +298,6 @@ class DartConstantCompiler extends ConstantCompilerBase {
|
| return definitions.getConstant(node);
|
| }
|
|
|
| - ConstantExpression getConstantForMetadata(MetadataAnnotation metadata) {
|
| - return metadata.constant;
|
| - }
|
| -
|
| ConstantExpression compileNodeWithDefinitions(Node node,
|
| TreeElements definitions,
|
| {bool isConst: true}) {
|
| @@ -312,23 +351,26 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
|
|
| AstConstant visitLiteralBool(LiteralBool node) {
|
| return new AstConstant(
|
| - context, node, new BoolConstantExpression(
|
| - node.value,
|
| - constantSystem.createBool(node.value)));
|
| + context,
|
| + node,
|
| + new BoolConstantExpression(node.value),
|
| + constantSystem.createBool(node.value));
|
| }
|
|
|
| AstConstant visitLiteralDouble(LiteralDouble node) {
|
| return new AstConstant(
|
| - context, node, new DoubleConstantExpression(
|
| - node.value,
|
| - constantSystem.createDouble(node.value)));
|
| + context,
|
| + node,
|
| + new DoubleConstantExpression(node.value),
|
| + constantSystem.createDouble(node.value));
|
| }
|
|
|
| AstConstant visitLiteralInt(LiteralInt node) {
|
| return new AstConstant(
|
| - context, node, new IntConstantExpression(
|
| - node.value,
|
| - constantSystem.createInt(node.value)));
|
| + context,
|
| + node,
|
| + new IntConstantExpression(node.value),
|
| + constantSystem.createInt(node.value));
|
| }
|
|
|
| AstConstant visitLiteralList(LiteralList node) {
|
| @@ -349,10 +391,10 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| }
|
| DartType type = elements.getType(node);
|
| return new AstConstant(
|
| - context, node, new ListConstantExpression(
|
| - constantSystem.createList(type, argumentValues),
|
| - type,
|
| - argumentExpressions));
|
| + context,
|
| + node,
|
| + new ListConstantExpression(type, argumentExpressions),
|
| + constantSystem.createList(type, argumentValues));
|
| }
|
|
|
| AstConstant visitLiteralMap(LiteralMap node) {
|
| @@ -360,9 +402,9 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| return signalNotCompileTimeConstant(node);
|
| }
|
| List<ConstantExpression> keyExpressions = <ConstantExpression>[];
|
| + List<ConstantExpression> valueExpressions = <ConstantExpression>[];
|
| List<ConstantValue> keyValues = <ConstantValue>[];
|
| - Map<ConstantValue, ConstantExpression> map =
|
| - new Map<ConstantValue, ConstantExpression>();
|
| + Map<ConstantValue, ConstantValue> map = <ConstantValue, ConstantValue>{};
|
| for (Link<Node> link = node.entries.nodes;
|
| !link.isEmpty;
|
| link = link.tail) {
|
| @@ -371,40 +413,45 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| if (key == null) {
|
| return null;
|
| }
|
| + AstConstant value = evaluateConstant(entry.value);
|
| + if (value == null) {
|
| + return null;
|
| + }
|
| if (!map.containsKey(key.value)) {
|
| - keyExpressions.add(key.expression);
|
| keyValues.add(key.value);
|
| } else {
|
| compiler.reportWarning(entry.key, MessageKind.EQUAL_MAP_ENTRY_KEY);
|
| }
|
| - AstConstant value = evaluateConstant(entry.value);
|
| - if (value == null) {
|
| - return null;
|
| - }
|
| - map[key.value] = value.expression;
|
| + keyExpressions.add(key.expression);
|
| + valueExpressions.add(value.expression);
|
| + map[key.value] = value.value;
|
| }
|
| - List<ConstantExpression> valueExpressions = map.values.toList();
|
| InterfaceType type = elements.getType(node);
|
| return new AstConstant(
|
| - context, node, new MapConstantExpression(
|
| - constantSystem.createMap(compiler, type, keyValues,
|
| - valueExpressions.map((e) => e.value).toList()),
|
| + context,
|
| + node,
|
| + new MapConstantExpression(
|
| type,
|
| keyExpressions,
|
| - valueExpressions));
|
| + valueExpressions),
|
| + constantSystem.createMap(
|
| + compiler, type, keyValues, map.values.toList()));
|
| }
|
|
|
| AstConstant visitLiteralNull(LiteralNull node) {
|
| return new AstConstant(
|
| - context, node, new NullConstantExpression(
|
| - constantSystem.createNull()));
|
| + context,
|
| + node,
|
| + new NullConstantExpression(),
|
| + constantSystem.createNull());
|
| }
|
|
|
| AstConstant visitLiteralString(LiteralString node) {
|
| return new AstConstant(
|
| - context, node, new StringConstantExpression(
|
| - node.dartString.slowToString(),
|
| - constantSystem.createString(node.dartString)));
|
| + context,
|
| + node,
|
| + new StringConstantExpression(node.dartString.slowToString()),
|
| + constantSystem.createString(node.dartString));
|
| }
|
|
|
| AstConstant visitStringJuxtaposition(StringJuxtaposition node) {
|
| @@ -414,11 +461,12 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| StringConstantValue leftValue = left.value;
|
| StringConstantValue rightValue = right.value;
|
| return new AstConstant(
|
| - context, node, new ConcatenateConstantExpression(
|
| - constantSystem.createString(
|
| - new DartString.concat(
|
| - leftValue.primitiveValue, rightValue.primitiveValue)),
|
| - [left.expression, right.expression]));
|
| + context,
|
| + node,
|
| + new ConcatenateConstantExpression([left.expression, right.expression]),
|
| + constantSystem.createString(
|
| + new DartString.concat(
|
| + leftValue.primitiveValue, rightValue.primitiveValue)));
|
| }
|
|
|
| AstConstant visitStringInterpolation(StringInterpolation node) {
|
| @@ -459,30 +507,31 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| new DartString.concat(accumulator, partStringValue.primitiveValue);
|
| };
|
| return new AstConstant(
|
| - context, node, new ConcatenateConstantExpression(
|
| - constantSystem.createString(accumulator),
|
| - subexpressions));
|
| + context,
|
| + node,
|
| + new ConcatenateConstantExpression(subexpressions),
|
| + constantSystem.createString(accumulator));
|
| }
|
|
|
| AstConstant visitLiteralSymbol(LiteralSymbol node) {
|
| InterfaceType type = compiler.symbolClass.rawType;
|
| String text = node.slowNameString;
|
| List<AstConstant> arguments =
|
| - <AstConstant>[new AstConstant(context, node,
|
| - new StringConstantExpression(
|
| - text,
|
| - constantSystem.createString(new LiteralDartString(text))))];
|
| + <AstConstant>[new AstConstant(
|
| + context,
|
| + node,
|
| + new StringConstantExpression(text),
|
| + constantSystem.createString(new LiteralDartString(text)))];
|
| ConstructorElement constructor = compiler.symbolConstructor;
|
| AstConstant constant = createConstructorInvocation(
|
| node, type, constructor, CallStructure.ONE_ARG,
|
| normalizedArguments: arguments);
|
| return new AstConstant(
|
| - context, node, new SymbolConstantExpression(constant.value, text));
|
| + context, node, new SymbolConstantExpression(text), constant.value);
|
| }
|
|
|
| - ConstantExpression makeTypeConstant(DartType elementType) {
|
| - return new TypeConstantExpression(
|
| - constantSystem.createType(compiler, elementType), elementType);
|
| + ConstantValue makeTypeConstant(DartType elementType) {
|
| + return constantSystem.createType(compiler, elementType);
|
| }
|
|
|
| /// Returns true if the prefix of the send resolves to a deferred import
|
| @@ -498,7 +547,8 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| if (Elements.isClass(element) || Elements.isTypedef(element)) {
|
| TypeDeclarationElement typeDeclarationElement = element;
|
| DartType type = typeDeclarationElement.rawType;
|
| - return new AstConstant(element, node, makeTypeConstant(type));
|
| + return new AstConstant(element, node,
|
| + new TypeConstantExpression(type), makeTypeConstant(type));
|
| }
|
| return signalNotCompileTimeConstant(node);
|
| }
|
| @@ -507,13 +557,15 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| AstConstant visitSend(Send send) {
|
| Element element = elements[send];
|
| if (send.isPropertyAccess) {
|
| - ConstantExpression result;
|
| -
|
| + AstConstant result;
|
| if (Elements.isStaticOrTopLevelFunction(element)) {
|
| FunctionElementX function = element;
|
| function.computeType(compiler);
|
| - result = new FunctionConstantExpression(
|
| - new FunctionConstantValue(function), function);
|
| + result = new AstConstant(
|
| + context,
|
| + send,
|
| + new FunctionConstantExpression(function),
|
| + new FunctionConstantValue(function));
|
| } else if (Elements.isStaticOrTopLevelField(element)) {
|
| ConstantExpression elementExpression;
|
| if (element.isConst) {
|
| @@ -522,12 +574,20 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| elementExpression = handler.compileVariable(element);
|
| }
|
| if (elementExpression != null) {
|
| - result =
|
| - new VariableConstantExpression(elementExpression.value, element);
|
| + result = new AstConstant(
|
| + context,
|
| + send,
|
| + new VariableConstantExpression(element),
|
| + handler.getConstantValue(elementExpression));
|
| }
|
| } else if (Elements.isClass(element) || Elements.isTypedef(element)) {
|
| assert(elements.isTypeLiteral(send));
|
| - result = makeTypeConstant(elements.getTypeLiteralType(send));
|
| + DartType elementType = elements.getTypeLiteralType(send);
|
| + result = new AstConstant(
|
| + context,
|
| + send,
|
| + new TypeConstantExpression(elementType),
|
| + makeTypeConstant(elementType));
|
| } else if (send.receiver != null) {
|
| if (send.selector.asIdentifier().source == "length") {
|
| AstConstant left = evaluate(send.receiver);
|
| @@ -535,8 +595,11 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| StringConstantValue stringConstantValue = left.value;
|
| DartString string = stringConstantValue.primitiveValue;
|
| IntConstantValue length = constantSystem.createInt(string.length);
|
| - result =
|
| - new StringLengthConstantExpression(length, left.expression);
|
| + result = new AstConstant(
|
| + context,
|
| + send,
|
| + new StringLengthConstantExpression(left.expression),
|
| + length);
|
| }
|
| }
|
| // Fall through to error handling.
|
| @@ -546,8 +609,11 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| ConstantExpression variableExpression =
|
| handler.compileConstant(element);
|
| if (variableExpression != null) {
|
| - result = new VariableConstantExpression(variableExpression.value,
|
| - element);
|
| + result = new AstConstant(
|
| + context,
|
| + send,
|
| + new VariableConstantExpression(element),
|
| + handler.getConstantValue(variableExpression));
|
| }
|
| }
|
| if (result == null) {
|
| @@ -559,14 +625,17 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| }
|
| PrefixElement prefix = compiler.deferredLoadTask
|
| .deferredPrefixElement(send, elements);
|
| - result = new DeferredConstantExpression(
|
| - new DeferredConstantValue(result.value, prefix),
|
| - result,
|
| - prefix);
|
| + result = new AstConstant(
|
| + context,
|
| + send,
|
| + new DeferredConstantExpression(
|
| + result.expression,
|
| + prefix),
|
| + new DeferredConstantValue(result.value, prefix));
|
| compiler.deferredLoadTask
|
| .registerConstantDeferredUse(result.value, prefix);
|
| }
|
| - return new AstConstant(context, send, result);
|
| + return result;
|
| } else if (send.isCall) {
|
| if (element == compiler.identicalFunction
|
| && send.argumentCount() == 2) {
|
| @@ -579,8 +648,11 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| constantSystem.identity.fold(left.value, right.value);
|
| if (result != null) {
|
| return new AstConstant(
|
| - context, send, new IdenticalConstantExpression(result,
|
| - left.expression, right.expression));
|
| + context,
|
| + send,
|
| + new IdenticalConstantExpression(
|
| + left.expression, right.expression),
|
| + result);
|
| }
|
| }
|
| return signalNotCompileTimeConstant(send);
|
| @@ -601,8 +673,11 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| return signalNotCompileTimeConstant(send);
|
| }
|
| return new AstConstant(
|
| - context, send, new UnaryConstantExpression(folded,
|
| - operator, receiverConstant.expression));
|
| + context,
|
| + send,
|
| + new UnaryConstantExpression(
|
| + operator, receiverConstant.expression),
|
| + folded);
|
| } else if (send.isOperator && !send.isPostfix) {
|
| assert(send.argumentCount() == 1);
|
| AstConstant left = evaluate(send.receiver);
|
| @@ -645,8 +720,11 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| return signalNotCompileTimeConstant(send);
|
| }
|
| return new AstConstant(
|
| - context, send, new BinaryConstantExpression(folded,
|
| - left.expression, operator, right.expression));
|
| + context,
|
| + send,
|
| + new BinaryConstantExpression(
|
| + left.expression, operator, right.expression),
|
| + folded);
|
| }
|
| return signalNotCompileTimeConstant(send);
|
| }
|
| @@ -672,13 +750,15 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| }
|
| BoolConstantValue boolCondition = condition.value;
|
| return new AstConstant(
|
| - context, node, new ConditionalConstantExpression(
|
| - boolCondition.primitiveValue
|
| - ? thenExpression.value
|
| - : elseExpression.value,
|
| + context,
|
| + node,
|
| + new ConditionalConstantExpression(
|
| condition.expression,
|
| thenExpression.expression,
|
| - elseExpression.expression));
|
| + elseExpression.expression),
|
| + boolCondition.primitiveValue
|
| + ? thenExpression.value
|
| + : elseExpression.value);
|
| }
|
|
|
| AstConstant visitSendSet(SendSet node) {
|
| @@ -702,7 +782,8 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
|
|
| AstConstant compileDefaultValue(VariableElement element) {
|
| ConstantExpression constant = handler.compileConstant(element);
|
| - return new AstConstant.fromDefaultValue(element, constant);
|
| + return new AstConstant.fromDefaultValue(
|
| + element, constant, handler.getConstantValue(constant));
|
| }
|
| target.computeSignature(compiler);
|
|
|
| @@ -774,14 +855,17 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| ConstructorElement implementation = target.implementation;
|
|
|
| if (implementation.isErroneous) {
|
| + // TODO(johnniwinther): This should probably be an [ErroneousAstConstant].
|
| return new AstConstant(
|
| - context, node, new ConstructedConstantExpression(
|
| - new ConstructedConstantValue(
|
| - constructedType, const <FieldElement, ConstantValue>{}),
|
| + context,
|
| + node,
|
| + new ConstructedConstantExpression(
|
| type,
|
| constructor,
|
| callStructure,
|
| - const <ConstantExpression>[]));
|
| + const <ConstantExpression>[]),
|
| + new ConstructedConstantValue(
|
| + constructedType, const <FieldElement, ConstantValue>{}));
|
| }
|
|
|
| List<AstConstant> concreteArguments;
|
| @@ -888,15 +972,15 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| }
|
| if (constructor == compiler.intEnvironment) {
|
| expression = new IntFromEnvironmentConstantExpression(
|
| - value, name, defaultValue);
|
| + name, defaultValue);
|
| } else if (constructor == compiler.boolEnvironment) {
|
| expression = new BoolFromEnvironmentConstantExpression(
|
| - value, name, defaultValue);
|
| + name, defaultValue);
|
| } else if (constructor == compiler.stringEnvironment) {
|
| expression = new StringFromEnvironmentConstantExpression(
|
| - value, name, defaultValue);
|
| + name, defaultValue);
|
| }
|
| - return new AstConstant(context, node, expression);
|
| + return new AstConstant(context, node, expression, value);
|
| }
|
|
|
| if (value == null) {
|
| @@ -939,8 +1023,7 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| assert(invariant(node, compiler.compilationFailed,
|
| message: "makeConstructedConstant can only be called with the "
|
| "effective target: $constructor"));
|
| - return new AstConstant(
|
| - context, node, new ErroneousConstantExpression());
|
| + return new ErroneousAstConstant(context, node);
|
| }
|
| assert(invariant(node, callStructure.signatureApplies(constructor) ||
|
| compiler.compilationFailed,
|
| @@ -958,12 +1041,14 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| fieldValues[field] = astConstant.value;
|
| });
|
| return new AstConstant(
|
| - context, node, new ConstructedConstantExpression(
|
| - new ConstructedConstantValue(constructedType, fieldValues),
|
| + context,
|
| + node,
|
| + new ConstructedConstantExpression(
|
| type,
|
| constructor,
|
| callStructure,
|
| - concreteArguments.map((e) => e.expression).toList()));
|
| + concreteArguments.map((e) => e.expression).toList()),
|
| + new ConstructedConstantValue(constructedType, fieldValues));
|
| }
|
|
|
| AstConstant visitParenthesizedExpression(ParenthesizedExpression node) {
|
| @@ -982,7 +1067,10 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| error(node, message);
|
|
|
| return new AstConstant(
|
| - null, node, new ErroneousConstantExpression());
|
| + context,
|
| + node,
|
| + new ErroneousConstantExpression(),
|
| + new NullConstantValue());
|
| }
|
| // Else we don't need to do anything. The final handler is only
|
| // optimistically trying to compile constants. So it is normal that we
|
| @@ -1188,8 +1276,11 @@ class ConstructorEvaluator extends CompileTimeConstantEvaluator {
|
| AstConstant fieldValue = fieldValues[field];
|
| if (fieldValue == null) {
|
| // Use the default value.
|
| + ConstantExpression fieldExpression = handler.compileConstant(field);
|
| fieldValue = new AstConstant.fromDefaultValue(
|
| - field, handler.compileConstant(field));
|
| + field,
|
| + fieldExpression,
|
| + handler.getConstantValue(fieldExpression));
|
| }
|
| fieldConstants[field] = fieldValue;
|
| },
|
| @@ -1211,27 +1302,30 @@ class AstConstant {
|
| final Element element;
|
| final Node node;
|
| final ConstantExpression expression;
|
| + final ConstantValue value;
|
|
|
| - AstConstant(this.element, this.node, this.expression);
|
| + AstConstant(this.element, this.node, this.expression, this.value);
|
|
|
| factory AstConstant.fromDefaultValue(
|
| VariableElement element,
|
| - ConstantExpression constant) {
|
| + ConstantExpression constant,
|
| + ConstantValue value) {
|
| return new AstConstant(
|
| element,
|
| element.initializer != null ? element.initializer : element.node,
|
| - constant);
|
| + constant,
|
| + value);
|
| }
|
|
|
| - ConstantValue get value => expression.value;
|
| -
|
| String toString() => expression.toString();
|
| }
|
|
|
| /// A synthetic constant used to recover from errors.
|
| class ErroneousAstConstant extends AstConstant {
|
| ErroneousAstConstant(Element element, Node node)
|
| - : super(element, node, new ErroneousConstantExpression());
|
| + : super(element, node,
|
| + // TODO(johnniwinther): Return a [NonConstantValue] instead.
|
| + new ErroneousConstantExpression(), new NullConstantValue());
|
| }
|
|
|
| // TODO(johnniwinther): Avoid the need for this hack.
|
|
|