| 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..e3f0c50d6c7c445e561919e3d76f1e8ba1bff13d 100644
|
| --- a/pkg/compiler/lib/src/compile_time_constants.dart
|
| +++ b/pkg/compiler/lib/src/compile_time_constants.dart
|
| @@ -12,6 +12,7 @@ import 'dart_types.dart';
|
| import 'dart2jslib.dart' show Compiler, CompilerTask, MessageKind, invariant;
|
| import 'elements/elements.dart';
|
| import 'elements/modelx.dart' show FunctionElementX;
|
| +import 'helpers/helpers.dart';
|
| import 'resolution/resolution.dart';
|
| import 'resolution/operators.dart';
|
| import 'tree/tree.dart';
|
| @@ -461,10 +462,10 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| new StringConstantExpression(
|
| text,
|
| constantSystem.createString(new LiteralDartString(text))))];
|
| - AstConstant constant = makeConstructedConstant(
|
| - compiler, handler, context, node, type, compiler.symbolConstructor,
|
| - CallStructure.ONE_ARG,
|
| - arguments, arguments);
|
| + 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));
|
| }
|
| @@ -713,7 +714,7 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| }
|
|
|
| Send send = node.send;
|
| - FunctionElement constructor = elements[send];
|
| + ConstructorElement constructor = elements[send];
|
| if (Elements.isUnresolved(constructor)) {
|
| return signalNotCompileTimeConstant(node);
|
| }
|
| @@ -725,119 +726,168 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| message: MessageKind.DEFERRED_COMPILE_TIME_CONSTANT_CONSTRUCTION);
|
| }
|
|
|
| + InterfaceType type = elements.getType(node);
|
| + CallStructure callStructure = elements.getSelector(send).callStructure;
|
| +
|
| + return createConstructorInvocation(
|
| + node, type, constructor, callStructure,
|
| + arguments: node.send.arguments);
|
| + }
|
| +
|
| + AstConstant createConstructorInvocation(
|
| + Node node,
|
| + InterfaceType type,
|
| + ConstructorElement constructor,
|
| + CallStructure callStructure,
|
| + {Link<Node> arguments,
|
| + List<AstConstant> normalizedArguments}) {
|
| // TODO(ahe): This is nasty: we must eagerly analyze the
|
| // constructor to ensure the redirectionTarget has been computed
|
| // correctly. Find a way to avoid this.
|
| compiler.analyzeElement(constructor.declaration);
|
|
|
| - InterfaceType type = elements.getType(node);
|
| - CallStructure callStructure = elements.getSelector(send).callStructure;
|
| + // The redirection chain of this element may not have been resolved through
|
| + // a post-process action, so we have to make sure it is done here.
|
| + compiler.resolver.resolveRedirectionChain(constructor, node);
|
| + InterfaceType constructedType =
|
| + constructor.computeEffectiveTargetType(type);
|
| + ConstructorElement target = constructor.effectiveTarget;
|
| + // The constructor must be an implementation to ensure that field
|
| + // initializers are handled correctly.
|
| + ConstructorElement implementation = target.implementation;
|
|
|
| - Map<Node, AstConstant> concreteArgumentMap =
|
| - <Node, AstConstant>{};
|
| - for (Link<Node> link = send.arguments; !link.isEmpty; link = link.tail) {
|
| - Node argument = link.head;
|
| - NamedArgument namedArgument = argument.asNamedArgument();
|
| - if (namedArgument != null) {
|
| - argument = namedArgument.expression;
|
| - }
|
| - concreteArgumentMap[argument] = evaluateConstant(argument);
|
| + if (implementation.isErroneous) {
|
| + return new AstConstant(
|
| + context, node, new ConstructedConstantExpression(
|
| + new ConstructedConstantValue(
|
| + constructedType, const <FieldElement, ConstantValue>{}),
|
| + type,
|
| + constructor,
|
| + callStructure,
|
| + const <ConstantExpression>[]));
|
| }
|
|
|
| - List<AstConstant> normalizedArguments =
|
| - evaluateArgumentsToConstructor(
|
| - node, callStructure, send.arguments, constructor.implementation,
|
| - compileArgument: (node) => concreteArgumentMap[node]);
|
| - List<AstConstant> concreteArguments =
|
| - concreteArgumentMap.values.toList();
|
| + List<AstConstant> concreteArguments;
|
| + if (arguments != null) {
|
| + Map<Node, AstConstant> concreteArgumentMap =
|
| + <Node, AstConstant>{};
|
| + for (Link<Node> link = arguments; !link.isEmpty; link = link.tail) {
|
| + Node argument = link.head;
|
| + NamedArgument namedArgument = argument.asNamedArgument();
|
| + if (namedArgument != null) {
|
| + argument = namedArgument.expression;
|
| + }
|
| + concreteArgumentMap[argument] = evaluateConstant(argument);
|
| + }
|
|
|
| - if (constructor == compiler.intEnvironment ||
|
| - constructor == compiler.boolEnvironment ||
|
| - constructor == compiler.stringEnvironment) {
|
| + normalizedArguments = evaluateArgumentsToConstructor(
|
| + node, callStructure, arguments, implementation,
|
| + compileArgument: (node) => concreteArgumentMap[node]);
|
| + concreteArguments = concreteArgumentMap.values.toList();
|
| + } else {
|
| + assert(normalizedArguments != null);
|
| + concreteArguments = normalizedArguments;
|
| + }
|
|
|
| - AstConstant createEvaluatedConstant(ConstantValue value) {
|
| - return new AstConstant(
|
| - context, node, new ConstructedConstantExpression(
|
| - value,
|
| - type,
|
| - constructor,
|
| - elements.getSelector(send).callStructure,
|
| - concreteArguments.map((e) => e.expression).toList()));
|
| - }
|
| + if (target == compiler.intEnvironment ||
|
| + target == compiler.boolEnvironment ||
|
| + target == compiler.stringEnvironment) {
|
| + return createFromEnvironmentConstant(
|
| + node, constructedType, target,
|
| + callStructure, normalizedArguments, concreteArguments);
|
| + } else {
|
| + return makeConstructedConstant(
|
| + compiler, handler, context, node,
|
| + type, constructor,
|
| + constructedType, implementation,
|
| + callStructure, concreteArguments, normalizedArguments);
|
| + }
|
| + }
|
|
|
| - var firstArgument = normalizedArguments[0].value;
|
| - ConstantValue defaultValue = normalizedArguments[1].value;
|
| + AstConstant createFromEnvironmentConstant(
|
| + Node node,
|
| + InterfaceType type,
|
| + ConstructorElement constructor,
|
| + CallStructure callStructure,
|
| + List<AstConstant> normalizedArguments,
|
| + List<AstConstant> concreteArguments) {
|
| + AstConstant createEvaluatedConstant(ConstantValue value) {
|
| + return new AstConstant(
|
| + context, node, new ConstructedConstantExpression(
|
| + value,
|
| + type,
|
| + constructor,
|
| + callStructure,
|
| + concreteArguments.map((e) => e.expression).toList()));
|
| + }
|
|
|
| - if (firstArgument.isNull) {
|
| - compiler.reportError(
|
| - send.arguments.head, MessageKind.NULL_NOT_ALLOWED);
|
| - return null;
|
| - }
|
| + var firstArgument = normalizedArguments[0].value;
|
| + ConstantValue defaultValue = normalizedArguments[1].value;
|
|
|
| - if (!firstArgument.isString) {
|
| - DartType type = defaultValue.getType(compiler.coreTypes);
|
| - compiler.reportError(
|
| - send.arguments.head, MessageKind.NOT_ASSIGNABLE,
|
| - {'fromType': type, 'toType': compiler.stringClass.rawType});
|
| - return null;
|
| - }
|
| + if (firstArgument.isNull) {
|
| + compiler.reportError(
|
| + normalizedArguments[0].node, MessageKind.NULL_NOT_ALLOWED);
|
| + return null;
|
| + }
|
|
|
| - if (constructor == compiler.intEnvironment &&
|
| - !(defaultValue.isNull || defaultValue.isInt)) {
|
| - DartType type = defaultValue.getType(compiler.coreTypes);
|
| - compiler.reportError(
|
| - send.arguments.tail.head, MessageKind.NOT_ASSIGNABLE,
|
| - {'fromType': type, 'toType': compiler.intClass.rawType});
|
| - return null;
|
| - }
|
| + if (!firstArgument.isString) {
|
| + DartType type = defaultValue.getType(compiler.coreTypes);
|
| + compiler.reportError(
|
| + normalizedArguments[0].node, MessageKind.NOT_ASSIGNABLE,
|
| + {'fromType': type, 'toType': compiler.stringClass.rawType});
|
| + return null;
|
| + }
|
|
|
| - if (constructor == compiler.boolEnvironment &&
|
| - !(defaultValue.isNull || defaultValue.isBool)) {
|
| - DartType type = defaultValue.getType(compiler.coreTypes);
|
| - compiler.reportError(
|
| - send.arguments.tail.head, MessageKind.NOT_ASSIGNABLE,
|
| - {'fromType': type, 'toType': compiler.boolClass.rawType});
|
| - return null;
|
| - }
|
| + if (constructor == compiler.intEnvironment &&
|
| + !(defaultValue.isNull || defaultValue.isInt)) {
|
| + DartType type = defaultValue.getType(compiler.coreTypes);
|
| + compiler.reportError(
|
| + normalizedArguments[1].node, MessageKind.NOT_ASSIGNABLE,
|
| + {'fromType': type, 'toType': compiler.intClass.rawType});
|
| + return null;
|
| + }
|
|
|
| - if (constructor == compiler.stringEnvironment &&
|
| - !(defaultValue.isNull || defaultValue.isString)) {
|
| - DartType type = defaultValue.getType(compiler.coreTypes);
|
| - compiler.reportError(
|
| - send.arguments.tail.head, MessageKind.NOT_ASSIGNABLE,
|
| - {'fromType': type, 'toType': compiler.stringClass.rawType});
|
| - return null;
|
| - }
|
| + if (constructor == compiler.boolEnvironment &&
|
| + !(defaultValue.isNull || defaultValue.isBool)) {
|
| + DartType type = defaultValue.getType(compiler.coreTypes);
|
| + compiler.reportError(
|
| + normalizedArguments[1].node, MessageKind.NOT_ASSIGNABLE,
|
| + {'fromType': type, 'toType': compiler.boolClass.rawType});
|
| + return null;
|
| + }
|
|
|
| - String value =
|
| - compiler.fromEnvironment(firstArgument.primitiveValue.slowToString());
|
| + if (constructor == compiler.stringEnvironment &&
|
| + !(defaultValue.isNull || defaultValue.isString)) {
|
| + DartType type = defaultValue.getType(compiler.coreTypes);
|
| + compiler.reportError(
|
| + normalizedArguments[1].node, MessageKind.NOT_ASSIGNABLE,
|
| + {'fromType': type, 'toType': compiler.stringClass.rawType});
|
| + return null;
|
| + }
|
|
|
| - if (value == null) {
|
| - return createEvaluatedConstant(defaultValue);
|
| - } else if (constructor == compiler.intEnvironment) {
|
| - int number = int.parse(value, onError: (_) => null);
|
| - return createEvaluatedConstant(
|
| - (number == null)
|
| - ? defaultValue
|
| - : constantSystem.createInt(number));
|
| - } else if (constructor == compiler.boolEnvironment) {
|
| - if (value == 'true') {
|
| - return createEvaluatedConstant(constantSystem.createBool(true));
|
| - } else if (value == 'false') {
|
| - return createEvaluatedConstant(constantSystem.createBool(false));
|
| - } else {
|
| - return createEvaluatedConstant(defaultValue);
|
| - }
|
| + String value =
|
| + compiler.fromEnvironment(firstArgument.primitiveValue.slowToString());
|
| +
|
| + if (value == null) {
|
| + return createEvaluatedConstant(defaultValue);
|
| + } else if (constructor == compiler.intEnvironment) {
|
| + int number = int.parse(value, onError: (_) => null);
|
| + return createEvaluatedConstant(
|
| + (number == null)
|
| + ? defaultValue
|
| + : constantSystem.createInt(number));
|
| + } else if (constructor == compiler.boolEnvironment) {
|
| + if (value == 'true') {
|
| + return createEvaluatedConstant(constantSystem.createBool(true));
|
| + } else if (value == 'false') {
|
| + return createEvaluatedConstant(constantSystem.createBool(false));
|
| } else {
|
| - assert(constructor == compiler.stringEnvironment);
|
| - return createEvaluatedConstant(
|
| - constantSystem.createString(new DartString.literal(value)));
|
| + return createEvaluatedConstant(defaultValue);
|
| }
|
| } else {
|
| - return makeConstructedConstant(
|
| - compiler, handler, context,
|
| - node, type, constructor, callStructure,
|
| - concreteArguments, normalizedArguments);
|
| + assert(constructor == compiler.stringEnvironment);
|
| + return createEvaluatedConstant(
|
| + constantSystem.createString(new DartString.literal(value)));
|
| }
|
| }
|
|
|
| @@ -848,31 +898,24 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| Node node,
|
| InterfaceType type,
|
| ConstructorElement constructor,
|
| + InterfaceType constructedType,
|
| + ConstructorElement target,
|
| CallStructure callStructure,
|
| List<AstConstant> concreteArguments,
|
| List<AstConstant> normalizedArguments) {
|
| + assert(invariant(node, !target.isRedirectingFactory,
|
| + message: "makeConstructedConstant can only be called with the "
|
| + "effective target: $constructor"));
|
| assert(invariant(node, callStructure.signatureApplies(constructor) ||
|
| compiler.compilationFailed,
|
| message: "Call structure $callStructure does not apply to constructor "
|
| "$constructor."));
|
|
|
| - // The redirection chain of this element may not have been resolved through
|
| - // a post-process action, so we have to make sure it is done here.
|
| - compiler.resolver.resolveRedirectionChain(constructor, node);
|
| - InterfaceType constructedType =
|
| - constructor.computeEffectiveTargetType(type);
|
| - ConstructorElement target = constructor.effectiveTarget;
|
| - ClassElement classElement = target.enclosingClass;
|
| - // The constructor must be an implementation to ensure that field
|
| - // initializers are handled correctly.
|
| - target = target.implementation;
|
| - assert(invariant(node, target.isImplementation));
|
| -
|
| ConstructorEvaluator evaluator = new ConstructorEvaluator(
|
| constructedType, target, handler, compiler);
|
| evaluator.evaluateConstructorFieldValues(normalizedArguments);
|
| Map<FieldElement, AstConstant> fieldConstants =
|
| - evaluator.buildFieldConstants(classElement);
|
| + evaluator.buildFieldConstants(target.enclosingClass);
|
| Map<FieldElement, ConstantValue> fieldValues =
|
| <FieldElement, ConstantValue>{};
|
| fieldConstants.forEach((FieldElement field, AstConstant astConstant) {
|
|
|