| 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 063653733088cc706e018863d7b6e861bb3f5597..8de6aae1d2e298b0788f5273dbcf8bd901ba625a 100644
|
| --- a/pkg/compiler/lib/src/compile_time_constants.dart
|
| +++ b/pkg/compiler/lib/src/compile_time_constants.dart
|
| @@ -10,7 +10,8 @@ import 'constants/evaluation.dart';
|
| import 'constants/expressions.dart';
|
| import 'constants/values.dart';
|
| import 'dart_types.dart';
|
| -import 'dart2jslib.dart' show Compiler, CompilerTask, MessageKind, WorldImpact, invariant;
|
| +import 'dart2jslib.dart'
|
| + show Compiler, CompilerTask, MessageKind, WorldImpact, invariant;
|
| import 'elements/elements.dart';
|
| import 'elements/modelx.dart' show FunctionElementX;
|
| import 'resolution/resolution.dart';
|
| @@ -66,7 +67,7 @@ abstract class ConstantCompiler extends ConstantEnvironment {
|
| ///
|
| /// The returned constant is always of the frontend interpretation.
|
| ConstantExpression compileNode(Node node, TreeElements elements,
|
| - {bool enforceConst: true});
|
| + {bool enforceConst: true});
|
|
|
| /// Compiles the compile-time constant for the value [metadata], or reports an
|
| /// error if the value is not a compile-time constant.
|
| @@ -159,7 +160,7 @@ abstract class ConstantCompilerBase implements ConstantCompiler {
|
| }
|
|
|
| ConstantExpression compileConstant(VariableElement element) {
|
| - return compileVariable(element, isConst: true);
|
| + return internalCompileVariable(element, true, true);
|
| }
|
|
|
| @override
|
| @@ -171,9 +172,15 @@ abstract class ConstantCompilerBase implements ConstantCompiler {
|
| });
|
| }
|
|
|
| - ConstantExpression compileVariable(VariableElement element,
|
| - {bool isConst: false}) {
|
| + ConstantExpression compileVariable(VariableElement element) {
|
| + return internalCompileVariable(element, false, true);
|
| + }
|
|
|
| + /// Compile [element] into a constant expression. If [isConst] is true,
|
| + /// then [element] is a constant variable. If [checkType] is true, then
|
| + /// report an error if [element] does not typecheck.
|
| + ConstantExpression internalCompileVariable(
|
| + VariableElement element, bool isConst, bool checkType) {
|
| if (initialVariableValues.containsKey(element.declaration)) {
|
| ConstantExpression result = initialVariableValues[element.declaration];
|
| return result;
|
| @@ -184,7 +191,8 @@ abstract class ConstantCompilerBase implements ConstantCompiler {
|
| _analyzeElementEagerly(compiler, currentElement);
|
|
|
| ConstantExpression constant = compileVariableWithDefinitions(
|
| - element, currentElement.resolvedAst.elements, isConst: isConst);
|
| + element, currentElement.resolvedAst.elements,
|
| + isConst: isConst, checkType: checkType);
|
| return constant;
|
| });
|
| }
|
| @@ -195,14 +203,13 @@ abstract class ConstantCompilerBase implements ConstantCompiler {
|
| * If the variable is `const` but cannot be compiled eagerly reports an
|
| * error.
|
| */
|
| - ConstantExpression compileVariableWithDefinitions(VariableElement element,
|
| - TreeElements definitions,
|
| - {bool isConst: false}) {
|
| + ConstantExpression compileVariableWithDefinitions(
|
| + VariableElement element, TreeElements definitions,
|
| + {bool isConst: false, bool checkType: true}) {
|
| Node node = element.node;
|
| if (pendingVariables.contains(element)) {
|
| if (isConst) {
|
| - compiler.reportError(
|
| - node, MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS);
|
| + compiler.reportError(node, MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS);
|
| ConstantExpression expression = new ErroneousConstantExpression();
|
| constantValueMap[expression] = constantSystem.createNull();
|
| return expression;
|
| @@ -218,9 +225,10 @@ abstract class ConstantCompilerBase implements ConstantCompiler {
|
| expression = new NullConstantExpression();
|
| constantValueMap[expression] = constantSystem.createNull();
|
| } else {
|
| - expression = compileNodeWithDefinitions(
|
| - initializer, definitions, isConst: isConst);
|
| + expression = compileNodeWithDefinitions(initializer, definitions,
|
| + isConst: isConst);
|
| if (compiler.enableTypeAssertions &&
|
| + checkType &&
|
| expression != null &&
|
| element.isField) {
|
| DartType elementType = element.type;
|
| @@ -236,12 +244,13 @@ abstract class ConstantCompilerBase implements ConstantCompiler {
|
| }
|
| } else {
|
| DartType constantType = value.getType(compiler.coreTypes);
|
| - if (!constantSystem.isSubtype(compiler.types,
|
| - constantType, elementType)) {
|
| + if (!constantSystem.isSubtype(
|
| + compiler.types, constantType, elementType)) {
|
| if (isConst) {
|
| - compiler.reportError(
|
| - node, MessageKind.NOT_ASSIGNABLE,
|
| - {'fromType': constantType, 'toType': elementType});
|
| + compiler.reportError(node, MessageKind.NOT_ASSIGNABLE, {
|
| + 'fromType': constantType,
|
| + 'toType': elementType
|
| + });
|
| } else {
|
| // If the field cannot be lazily initialized, we will throw
|
| // the exception at runtime.
|
| @@ -255,7 +264,7 @@ abstract class ConstantCompilerBase implements ConstantCompiler {
|
| initialVariableValues[element.declaration] = expression;
|
| } else {
|
| assert(invariant(element, !isConst,
|
| - message: "Variable $element does not compile to a constant."));
|
| + message: "Variable $element does not compile to a constant."));
|
| }
|
| pendingVariables.remove(element);
|
| return expression;
|
| @@ -265,9 +274,8 @@ abstract class ConstantCompilerBase implements ConstantCompiler {
|
| constantValueMap[expression] = value;
|
| }
|
|
|
| - ConstantExpression compileNodeWithDefinitions(Node node,
|
| - TreeElements definitions,
|
| - {bool isConst: true}) {
|
| + ConstantExpression compileNodeWithDefinitions(
|
| + Node node, TreeElements definitions, {bool isConst: true}) {
|
| assert(node != null);
|
| CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator(
|
| this, definitions, compiler, isConst: isConst);
|
| @@ -284,13 +292,12 @@ abstract class ConstantCompilerBase implements ConstantCompiler {
|
| }
|
|
|
| ConstantExpression compileNode(Node node, TreeElements elements,
|
| - {bool enforceConst: true}) {
|
| + {bool enforceConst: true}) {
|
| return compileNodeWithDefinitions(node, elements, isConst: enforceConst);
|
| }
|
|
|
| - ConstantExpression compileMetadata(MetadataAnnotation metadata,
|
| - Node node,
|
| - TreeElements elements) {
|
| + ConstantExpression compileMetadata(
|
| + MetadataAnnotation metadata, Node node, TreeElements elements) {
|
| return compileNodeWithDefinitions(node, elements);
|
| }
|
|
|
| @@ -315,9 +322,8 @@ class DartConstantCompiler extends ConstantCompilerBase {
|
| return definitions.getConstant(node);
|
| }
|
|
|
| - ConstantExpression compileNodeWithDefinitions(Node node,
|
| - TreeElements definitions,
|
| - {bool isConst: true}) {
|
| + ConstantExpression compileNodeWithDefinitions(
|
| + Node node, TreeElements definitions, {bool isConst: true}) {
|
| ConstantExpression constant = definitions.getConstant(node);
|
| if (constant != null && getConstantValue(constant) != null) {
|
| return constant;
|
| @@ -341,10 +347,8 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
|
|
| Element get context => elements.analyzedElement;
|
|
|
| - CompileTimeConstantEvaluator(this.handler,
|
| - this.elements,
|
| - this.compiler,
|
| - {bool isConst: false})
|
| + CompileTimeConstantEvaluator(this.handler, this.elements, this.compiler,
|
| + {bool isConst: false})
|
| : this.isEvaluatingConstant = isConst;
|
|
|
| ConstantSystem get constantSystem => handler.constantSystem;
|
| @@ -369,38 +373,31 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| }
|
|
|
| AstConstant visitLiteralBool(LiteralBool node) {
|
| - return new AstConstant(
|
| - context,
|
| - node,
|
| + return new AstConstant(context, node,
|
| new BoolConstantExpression(node.value),
|
| constantSystem.createBool(node.value));
|
| }
|
|
|
| AstConstant visitLiteralDouble(LiteralDouble node) {
|
| - return new AstConstant(
|
| - context,
|
| - node,
|
| + return new AstConstant(context, node,
|
| new DoubleConstantExpression(node.value),
|
| constantSystem.createDouble(node.value));
|
| }
|
|
|
| AstConstant visitLiteralInt(LiteralInt node) {
|
| - return new AstConstant(
|
| - context,
|
| - node,
|
| - new IntConstantExpression(node.value),
|
| + return new AstConstant(context, node, new IntConstantExpression(node.value),
|
| constantSystem.createInt(node.value));
|
| }
|
|
|
| AstConstant visitLiteralList(LiteralList node) {
|
| - if (!node.isConst) {
|
| + if (!node.isConst) {
|
| return signalNotCompileTimeConstant(node);
|
| }
|
| List<ConstantExpression> argumentExpressions = <ConstantExpression>[];
|
| List<ConstantValue> argumentValues = <ConstantValue>[];
|
| for (Link<Node> link = node.elements.nodes;
|
| - !link.isEmpty;
|
| - link = link.tail) {
|
| + !link.isEmpty;
|
| + link = link.tail) {
|
| AstConstant argument = evaluateConstant(link.head);
|
| if (argument == null) {
|
| return null;
|
| @@ -409,9 +406,7 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| argumentValues.add(argument.value);
|
| }
|
| DartType type = elements.getType(node);
|
| - return new AstConstant(
|
| - context,
|
| - node,
|
| + return new AstConstant(context, node,
|
| new ListConstantExpression(type, argumentExpressions),
|
| constantSystem.createList(type, argumentValues));
|
| }
|
| @@ -425,8 +420,8 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| List<ConstantValue> keyValues = <ConstantValue>[];
|
| Map<ConstantValue, ConstantValue> map = <ConstantValue, ConstantValue>{};
|
| for (Link<Node> link = node.entries.nodes;
|
| - !link.isEmpty;
|
| - link = link.tail) {
|
| + !link.isEmpty;
|
| + link = link.tail) {
|
| LiteralMapEntry entry = link.head;
|
| AstConstant key = evaluateConstant(entry.key);
|
| if (key == null) {
|
| @@ -446,29 +441,19 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| map[key.value] = value.value;
|
| }
|
| InterfaceType type = elements.getType(node);
|
| - return new AstConstant(
|
| - context,
|
| - node,
|
| - new MapConstantExpression(
|
| - type,
|
| - keyExpressions,
|
| - valueExpressions),
|
| + return new AstConstant(context, node,
|
| + new MapConstantExpression(type, keyExpressions, valueExpressions),
|
| constantSystem.createMap(
|
| compiler, type, keyValues, map.values.toList()));
|
| }
|
|
|
| AstConstant visitLiteralNull(LiteralNull node) {
|
| - return new AstConstant(
|
| - context,
|
| - node,
|
| - new NullConstantExpression(),
|
| + return new AstConstant(context, node, new NullConstantExpression(),
|
| constantSystem.createNull());
|
| }
|
|
|
| AstConstant visitLiteralString(LiteralString node) {
|
| - return new AstConstant(
|
| - context,
|
| - node,
|
| + return new AstConstant(context, node,
|
| new StringConstantExpression(node.dartString.slowToString()),
|
| constantSystem.createString(node.dartString));
|
| }
|
| @@ -479,13 +464,10 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| if (left == null || right == null) return null;
|
| StringConstantValue leftValue = left.value;
|
| StringConstantValue rightValue = right.value;
|
| - return new AstConstant(
|
| - context,
|
| - node,
|
| + return new AstConstant(context, node,
|
| new ConcatenateConstantExpression([left.expression, right.expression]),
|
| - constantSystem.createString(
|
| - new DartString.concat(
|
| - leftValue.primitiveValue, rightValue.primitiveValue)));
|
| + constantSystem.createString(new DartString.concat(
|
| + leftValue.primitiveValue, rightValue.primitiveValue)));
|
| }
|
|
|
| AstConstant visitStringInterpolation(StringInterpolation node) {
|
| @@ -524,10 +506,9 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| StringConstantValue partStringValue = partString.value;
|
| accumulator =
|
| new DartString.concat(accumulator, partStringValue.primitiveValue);
|
| - };
|
| - return new AstConstant(
|
| - context,
|
| - node,
|
| + }
|
| + ;
|
| + return new AstConstant(context, node,
|
| new ConcatenateConstantExpression(subexpressions),
|
| constantSystem.createString(accumulator));
|
| }
|
| @@ -535,12 +516,10 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| 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)))];
|
| + List<AstConstant> arguments = <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,
|
| @@ -557,8 +536,8 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| /// prefix.
|
| bool isDeferredUse(Send send) {
|
| if (send == null) return false;
|
| - return compiler.deferredLoadTask
|
| - .deferredPrefixElement(send, elements) != null;
|
| + return compiler.deferredLoadTask.deferredPrefixElement(send, elements) !=
|
| + null;
|
| }
|
|
|
| AstConstant visitIdentifier(Identifier node) {
|
| @@ -566,8 +545,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,
|
| - new TypeConstantExpression(type), makeTypeConstant(type));
|
| + return new AstConstant(element, node, new TypeConstantExpression(type),
|
| + makeTypeConstant(type));
|
| }
|
| return signalNotCompileTimeConstant(node);
|
| }
|
| @@ -580,9 +559,7 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| if (Elements.isStaticOrTopLevelFunction(element)) {
|
| FunctionElementX function = element;
|
| function.computeType(compiler);
|
| - result = new AstConstant(
|
| - context,
|
| - send,
|
| + result = new AstConstant(context, send,
|
| new FunctionConstantExpression(function),
|
| new FunctionConstantValue(function));
|
| } else if (Elements.isStaticOrTopLevelField(element)) {
|
| @@ -593,18 +570,14 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| elementExpression = handler.compileVariable(element);
|
| }
|
| if (elementExpression != null) {
|
| - result = new AstConstant(
|
| - context,
|
| - send,
|
| + result = new AstConstant(context, send,
|
| new VariableConstantExpression(element),
|
| handler.getConstantValue(elementExpression));
|
| }
|
| } else if (Elements.isClass(element) || Elements.isTypedef(element)) {
|
| assert(elements.isTypeLiteral(send));
|
| DartType elementType = elements.getTypeLiteralType(send);
|
| - result = new AstConstant(
|
| - context,
|
| - send,
|
| + result = new AstConstant(context, send,
|
| new TypeConstantExpression(elementType),
|
| makeTypeConstant(elementType));
|
| } else if (send.receiver != null) {
|
| @@ -614,23 +587,18 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| StringConstantValue stringConstantValue = left.value;
|
| DartString string = stringConstantValue.primitiveValue;
|
| IntConstantValue length = constantSystem.createInt(string.length);
|
| - result = new AstConstant(
|
| - context,
|
| - send,
|
| - new StringLengthConstantExpression(left.expression),
|
| - length);
|
| + result = new AstConstant(context, send,
|
| + new StringLengthConstantExpression(left.expression), length);
|
| }
|
| }
|
| // Fall through to error handling.
|
| - } else if (!Elements.isUnresolved(element)
|
| - && element.isVariable
|
| - && element.isConst) {
|
| + } else if (!Elements.isUnresolved(element) &&
|
| + element.isVariable &&
|
| + element.isConst) {
|
| ConstantExpression variableExpression =
|
| handler.compileConstant(element);
|
| if (variableExpression != null) {
|
| - result = new AstConstant(
|
| - context,
|
| - send,
|
| + result = new AstConstant(context, send,
|
| new VariableConstantExpression(element),
|
| handler.getConstantValue(variableExpression));
|
| }
|
| @@ -642,22 +610,17 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| if (isEvaluatingConstant) {
|
| error(send, MessageKind.DEFERRED_COMPILE_TIME_CONSTANT);
|
| }
|
| - PrefixElement prefix = compiler.deferredLoadTask
|
| - .deferredPrefixElement(send, elements);
|
| - result = new AstConstant(
|
| - context,
|
| - send,
|
| - new DeferredConstantExpression(
|
| - result.expression,
|
| - prefix),
|
| + PrefixElement prefix =
|
| + compiler.deferredLoadTask.deferredPrefixElement(send, elements);
|
| + result = new AstConstant(context, send,
|
| + new DeferredConstantExpression(result.expression, prefix),
|
| new DeferredConstantValue(result.value, prefix));
|
| - compiler.deferredLoadTask
|
| - .registerConstantDeferredUse(result.value, prefix);
|
| + compiler.deferredLoadTask.registerConstantDeferredUse(
|
| + result.value, prefix);
|
| }
|
| return result;
|
| } else if (send.isCall) {
|
| - if (element == compiler.identicalFunction
|
| - && send.argumentCount() == 2) {
|
| + if (element == compiler.identicalFunction && send.argumentCount() == 2) {
|
| AstConstant left = evaluate(send.argumentsNode.nodes.head);
|
| AstConstant right = evaluate(send.argumentsNode.nodes.tail.head);
|
| if (left == null || right == null) {
|
| @@ -666,12 +629,8 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| ConstantValue result =
|
| constantSystem.identity.fold(left.value, right.value);
|
| if (result != null) {
|
| - return new AstConstant(
|
| - context,
|
| - send,
|
| - new IdenticalConstantExpression(
|
| - left.expression, right.expression),
|
| - result);
|
| + return new AstConstant(context, send, new IdenticalConstantExpression(
|
| + left.expression, right.expression), result);
|
| }
|
| }
|
| return signalNotCompileTimeConstant(send);
|
| @@ -691,11 +650,8 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| if (folded == null) {
|
| return signalNotCompileTimeConstant(send);
|
| }
|
| - return new AstConstant(
|
| - context,
|
| - send,
|
| - new UnaryConstantExpression(
|
| - operator, receiverConstant.expression),
|
| + return new AstConstant(context, send,
|
| + new UnaryConstantExpression(operator, receiverConstant.expression),
|
| folded);
|
| } else if (send.isOperator && !send.isPostfix) {
|
| assert(send.argumentCount() == 1);
|
| @@ -738,12 +694,8 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| if (folded == null) {
|
| return signalNotCompileTimeConstant(send);
|
| }
|
| - return new AstConstant(
|
| - context,
|
| - send,
|
| - new BinaryConstantExpression(
|
| - left.expression, operator, right.expression),
|
| - folded);
|
| + return new AstConstant(context, send, new BinaryConstantExpression(
|
| + left.expression, operator, right.expression), folded);
|
| }
|
| return signalNotCompileTimeConstant(send);
|
| }
|
| @@ -755,9 +707,10 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| } else if (!condition.value.isBool) {
|
| DartType conditionType = condition.value.getType(compiler.coreTypes);
|
| if (isEvaluatingConstant) {
|
| - compiler.reportError(
|
| - node.condition, MessageKind.NOT_ASSIGNABLE,
|
| - {'fromType': conditionType, 'toType': compiler.boolClass.rawType});
|
| + compiler.reportError(node.condition, MessageKind.NOT_ASSIGNABLE, {
|
| + 'fromType': conditionType,
|
| + 'toType': compiler.boolClass.rawType
|
| + });
|
| return new ErroneousAstConstant(context, node);
|
| }
|
| return null;
|
| @@ -768,16 +721,11 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| return null;
|
| }
|
| BoolConstantValue boolCondition = condition.value;
|
| - return new AstConstant(
|
| - context,
|
| - node,
|
| - new ConditionalConstantExpression(
|
| - condition.expression,
|
| - thenExpression.expression,
|
| - elseExpression.expression),
|
| - boolCondition.primitiveValue
|
| - ? thenExpression.value
|
| - : elseExpression.value);
|
| + return new AstConstant(context, node, new ConditionalConstantExpression(
|
| + condition.expression, thenExpression.expression,
|
| + elseExpression.expression), boolCondition.primitiveValue
|
| + ? thenExpression.value
|
| + : elseExpression.value);
|
| }
|
|
|
| AstConstant visitSendSet(SendSet node) {
|
| @@ -791,12 +739,9 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| *
|
| * Invariant: [target] must be an implementation element.
|
| */
|
| - List<AstConstant> evaluateArgumentsToConstructor(
|
| - Node node,
|
| - CallStructure callStructure,
|
| - Link<Node> arguments,
|
| - ConstructorElement target,
|
| - {AstConstant compileArgument(Node node)}) {
|
| + List<AstConstant> evaluateArgumentsToConstructor(Node node,
|
| + CallStructure callStructure, Link<Node> arguments,
|
| + ConstructorElement target, {AstConstant compileArgument(Node node)}) {
|
| assert(invariant(node, target.isImplementation));
|
|
|
| AstConstant compileDefaultValue(VariableElement element) {
|
| @@ -810,20 +755,16 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| if (!callStructure.signatureApplies(signature)) {
|
| String name = Elements.constructorNameForDiagnostics(
|
| target.enclosingClass.name, target.name);
|
| - compiler.reportError(
|
| - node,
|
| - MessageKind.INVALID_CONSTRUCTOR_ARGUMENTS,
|
| - {'constructorName': name});
|
| + compiler.reportError(node, MessageKind.INVALID_CONSTRUCTOR_ARGUMENTS, {
|
| + 'constructorName': name
|
| + });
|
|
|
| return new List<AstConstant>.filled(
|
| target.functionSignature.parameterCount,
|
| new ErroneousAstConstant(context, node));
|
| }
|
| return callStructure.makeArgumentsList(
|
| - arguments,
|
| - target,
|
| - compileArgument,
|
| - compileDefaultValue);
|
| + arguments, target, compileArgument, compileDefaultValue);
|
| }
|
|
|
| AstConstant visitNewExpression(NewExpression node) {
|
| @@ -847,18 +788,13 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| InterfaceType type = elements.getType(node);
|
| CallStructure callStructure = elements.getSelector(send).callStructure;
|
|
|
| - return createConstructorInvocation(
|
| - node, type, constructor, 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}) {
|
| + 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.
|
| @@ -876,22 +812,15 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
|
|
| if (implementation.isErroneous) {
|
| // TODO(johnniwinther): This should probably be an [ErroneousAstConstant].
|
| - return new AstConstant(
|
| - context,
|
| - node,
|
| - new ConstructedConstantExpression(
|
| - type,
|
| - constructor,
|
| - callStructure,
|
| - const <ConstantExpression>[]),
|
| + return new AstConstant(context, node, new ConstructedConstantExpression(
|
| + type, constructor, callStructure, const <ConstantExpression>[]),
|
| new ConstructedConstantValue(
|
| constructedType, const <FieldElement, ConstantValue>{}));
|
| }
|
|
|
| List<AstConstant> concreteArguments;
|
| if (arguments != null) {
|
| - Map<Node, AstConstant> concreteArgumentMap =
|
| - <Node, AstConstant>{};
|
| + Map<Node, AstConstant> concreteArgumentMap = <Node, AstConstant>{};
|
| for (Link<Node> link = arguments; !link.isEmpty; link = link.tail) {
|
| Node argument = link.head;
|
| NamedArgument namedArgument = argument.asNamedArgument();
|
| @@ -913,26 +842,19 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| if (target == compiler.intEnvironment ||
|
| target == compiler.boolEnvironment ||
|
| target == compiler.stringEnvironment) {
|
| - return createFromEnvironmentConstant(
|
| - node, constructedType, target,
|
| + return createFromEnvironmentConstant(node, constructedType, target,
|
| callStructure, normalizedArguments, concreteArguments);
|
| } else {
|
| - return makeConstructedConstant(
|
| - compiler, handler, context, node,
|
| - type, constructor,
|
| - constructedType, implementation,
|
| - callStructure, concreteArguments, normalizedArguments);
|
| + return makeConstructedConstant(compiler, handler, context, node, type,
|
| + constructor, constructedType, implementation, callStructure,
|
| + concreteArguments, normalizedArguments);
|
| }
|
| }
|
|
|
| - AstConstant createFromEnvironmentConstant(
|
| - Node node,
|
| - InterfaceType type,
|
| - ConstructorElement constructor,
|
| - CallStructure callStructure,
|
| + AstConstant createFromEnvironmentConstant(Node node, InterfaceType type,
|
| + ConstructorElement constructor, CallStructure callStructure,
|
| List<AstConstant> normalizedArguments,
|
| List<AstConstant> concreteArguments) {
|
| -
|
| var firstArgument = normalizedArguments[0].value;
|
| ConstantValue defaultValue = normalizedArguments[1].value;
|
|
|
| @@ -944,46 +866,51 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
|
|
| if (!firstArgument.isString) {
|
| DartType type = defaultValue.getType(compiler.coreTypes);
|
| - compiler.reportError(
|
| - normalizedArguments[0].node, MessageKind.NOT_ASSIGNABLE,
|
| - {'fromType': type, 'toType': compiler.stringClass.rawType});
|
| + compiler.reportError(normalizedArguments[0].node,
|
| + MessageKind.NOT_ASSIGNABLE, {
|
| + 'fromType': type,
|
| + 'toType': compiler.stringClass.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});
|
| + compiler.reportError(normalizedArguments[1].node,
|
| + MessageKind.NOT_ASSIGNABLE, {
|
| + 'fromType': type,
|
| + 'toType': compiler.intClass.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});
|
| + compiler.reportError(normalizedArguments[1].node,
|
| + MessageKind.NOT_ASSIGNABLE, {
|
| + 'fromType': type,
|
| + 'toType': compiler.boolClass.rawType
|
| + });
|
| return null;
|
| }
|
|
|
| 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});
|
| + compiler.reportError(normalizedArguments[1].node,
|
| + MessageKind.NOT_ASSIGNABLE, {
|
| + 'fromType': type,
|
| + 'toType': compiler.stringClass.rawType
|
| + });
|
| return null;
|
| }
|
|
|
| - String name =
|
| - firstArgument.primitiveValue.slowToString();
|
| - String value =
|
| - compiler.fromEnvironment(name);
|
| + String name = firstArgument.primitiveValue.slowToString();
|
| + String value = compiler.fromEnvironment(name);
|
|
|
| AstConstant createEvaluatedConstant(ConstantValue value) {
|
| -
|
| ConstantExpression expression;
|
| ConstantExpression name = concreteArguments[0].expression;
|
| ConstantExpression defaultValue;
|
| @@ -991,14 +918,14 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| defaultValue = concreteArguments[1].expression;
|
| }
|
| if (constructor == compiler.intEnvironment) {
|
| - expression = new IntFromEnvironmentConstantExpression(
|
| - name, defaultValue);
|
| + expression =
|
| + new IntFromEnvironmentConstantExpression(name, defaultValue);
|
| } else if (constructor == compiler.boolEnvironment) {
|
| - expression = new BoolFromEnvironmentConstantExpression(
|
| - name, defaultValue);
|
| + expression =
|
| + new BoolFromEnvironmentConstantExpression(name, defaultValue);
|
| } else if (constructor == compiler.stringEnvironment) {
|
| - expression = new StringFromEnvironmentConstantExpression(
|
| - name, defaultValue);
|
| + expression =
|
| + new StringFromEnvironmentConstantExpression(name, defaultValue);
|
| }
|
| return new AstConstant(context, node, expression, value);
|
| }
|
| @@ -1008,9 +935,7 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| } else if (constructor == compiler.intEnvironment) {
|
| int number = int.parse(value, onError: (_) => null);
|
| return createEvaluatedConstant(
|
| - (number == null)
|
| - ? defaultValue
|
| - : constantSystem.createInt(number));
|
| + (number == null) ? defaultValue : constantSystem.createInt(number));
|
| } else if (constructor == compiler.boolEnvironment) {
|
| if (value == 'true') {
|
| return createEvaluatedConstant(constantSystem.createBool(true));
|
| @@ -1026,34 +951,27 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| }
|
| }
|
|
|
| - static AstConstant makeConstructedConstant(
|
| - Compiler compiler,
|
| - ConstantCompilerBase handler,
|
| - Element context,
|
| - Node node,
|
| - InterfaceType type,
|
| - ConstructorElement constructor,
|
| - InterfaceType constructedType,
|
| - ConstructorElement target,
|
| - CallStructure callStructure,
|
| - List<AstConstant> concreteArguments,
|
| + static AstConstant makeConstructedConstant(Compiler compiler,
|
| + ConstantCompilerBase handler, Element context, Node node,
|
| + InterfaceType type, ConstructorElement constructor,
|
| + InterfaceType constructedType, ConstructorElement target,
|
| + CallStructure callStructure, List<AstConstant> concreteArguments,
|
| List<AstConstant> normalizedArguments) {
|
| if (target.isRedirectingFactory) {
|
| // This happens is case of cyclic redirection.
|
| assert(invariant(node, compiler.compilationFailed,
|
| message: "makeConstructedConstant can only be called with the "
|
| - "effective target: $constructor"));
|
| + "effective target: $constructor"));
|
| return new ErroneousAstConstant(context, node);
|
| }
|
| - assert(invariant(
|
| - node,
|
| + assert(invariant(node,
|
| callStructure.signatureApplies(constructor.functionSignature) ||
|
| compiler.compilationFailed,
|
| message: "Call structure $callStructure does not apply to constructor "
|
| - "$constructor."));
|
| + "$constructor."));
|
|
|
| - ConstructorEvaluator evaluator = new ConstructorEvaluator(
|
| - constructedType, target, handler, compiler);
|
| + ConstructorEvaluator evaluator =
|
| + new ConstructorEvaluator(constructedType, target, handler, compiler);
|
| evaluator.evaluateConstructorFieldValues(normalizedArguments);
|
| Map<FieldElement, AstConstant> fieldConstants =
|
| evaluator.buildFieldConstants(target.enclosingClass);
|
| @@ -1062,13 +980,8 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| fieldConstants.forEach((FieldElement field, AstConstant astConstant) {
|
| fieldValues[field] = astConstant.value;
|
| });
|
| - return new AstConstant(
|
| - context,
|
| - node,
|
| - new ConstructedConstantExpression(
|
| - type,
|
| - constructor,
|
| - callStructure,
|
| + return new AstConstant(context, node, new ConstructedConstantExpression(
|
| + type, constructor, callStructure,
|
| concreteArguments.map((e) => e.expression).toList()),
|
| new ConstructedConstantValue(constructedType, fieldValues));
|
| }
|
| @@ -1088,10 +1001,7 @@ class CompileTimeConstantEvaluator extends Visitor<AstConstant> {
|
| if (isEvaluatingConstant) {
|
| error(node, message);
|
|
|
| - return new AstConstant(
|
| - context,
|
| - node,
|
| - new ErroneousConstantExpression(),
|
| + return new AstConstant(context, node, new ErroneousConstantExpression(),
|
| new NullConstantValue());
|
| }
|
| // Else we don't need to do anything. The final handler is only
|
| @@ -1115,16 +1025,12 @@ class ConstructorEvaluator extends CompileTimeConstantEvaluator {
|
| * Invariant: [constructor] must be an implementation element.
|
| */
|
| ConstructorEvaluator(InterfaceType this.constructedType,
|
| - FunctionElement constructor,
|
| - ConstantCompiler handler,
|
| - Compiler compiler)
|
| + FunctionElement constructor, ConstantCompiler handler, Compiler compiler)
|
| : this.constructor = constructor,
|
| this.definitions = new Map<Element, AstConstant>(),
|
| this.fieldValues = new Map<Element, AstConstant>(),
|
| - super(handler,
|
| - _analyzeElementEagerly(compiler, constructor),
|
| - compiler,
|
| - isConst: true) {
|
| + super(handler, _analyzeElementEagerly(compiler, constructor), compiler,
|
| + isConst: true) {
|
| assert(invariant(constructor, constructor.isImplementation));
|
| }
|
|
|
| @@ -1140,27 +1046,24 @@ class ConstructorEvaluator extends CompileTimeConstantEvaluator {
|
| return super.visitSend(send);
|
| }
|
|
|
| - void potentiallyCheckType(Node node,
|
| - TypedElement element,
|
| - AstConstant constant) {
|
| + void potentiallyCheckType(TypedElement element, AstConstant constant) {
|
| if (compiler.enableTypeAssertions) {
|
| DartType elementType = element.type.substByContext(constructedType);
|
| DartType constantType = constant.value.getType(compiler.coreTypes);
|
| - if (!constantSystem.isSubtype(compiler.types,
|
| - constantType, elementType)) {
|
| + if (!constantSystem.isSubtype(
|
| + compiler.types, constantType, elementType)) {
|
| compiler.withCurrentElement(constant.element, () {
|
| - compiler.reportError(
|
| - constant.node, MessageKind.NOT_ASSIGNABLE,
|
| - {'fromType': constantType, 'toType': elementType});
|
| + compiler.reportError(constant.node, MessageKind.NOT_ASSIGNABLE, {
|
| + 'fromType': constantType,
|
| + 'toType': elementType
|
| + });
|
| });
|
| }
|
| }
|
| }
|
|
|
| - void updateFieldValue(Node node,
|
| - TypedElement element,
|
| - AstConstant constant) {
|
| - potentiallyCheckType(node, element, constant);
|
| + void updateFieldValue(Node node, TypedElement element, AstConstant constant) {
|
| + potentiallyCheckType(element, constant);
|
| fieldValues[element] = constant;
|
| }
|
|
|
| @@ -1181,14 +1084,14 @@ class ConstructorEvaluator extends CompileTimeConstantEvaluator {
|
| InitializingFormalElement initializingFormal = parameter;
|
| updateFieldValue(node, initializingFormal.fieldElement, argument);
|
| } else {
|
| - potentiallyCheckType(node, parameter, argument);
|
| + potentiallyCheckType(parameter, argument);
|
| definitions[parameter] = argument;
|
| }
|
| });
|
| }
|
|
|
| - void evaluateSuperOrRedirectSend(List<AstConstant> compiledArguments,
|
| - FunctionElement targetConstructor) {
|
| + void evaluateSuperOrRedirectSend(
|
| + List<AstConstant> compiledArguments, FunctionElement targetConstructor) {
|
| ConstructorEvaluator evaluator = new ConstructorEvaluator(
|
| constructedType.asInstanceOf(targetConstructor.enclosingClass),
|
| targetConstructor, handler, compiler);
|
| @@ -1210,12 +1113,8 @@ class ConstructorEvaluator extends CompileTimeConstantEvaluator {
|
| Function compileArgument = (element) => definitions[element];
|
| Function compileConstant = handler.compileConstant;
|
| FunctionElement target = constructor.definingConstructor.implementation;
|
| - CallStructure.addForwardingElementArgumentsToList(
|
| - constructor,
|
| - compiledArguments,
|
| - target,
|
| - compileArgument,
|
| - compileConstant);
|
| + CallStructure.addForwardingElementArgumentsToList(constructor,
|
| + compiledArguments, target, compileArgument, compileConstant);
|
| evaluateSuperOrRedirectSend(compiledArguments, target);
|
| return;
|
| }
|
| @@ -1226,18 +1125,16 @@ class ConstructorEvaluator extends CompileTimeConstantEvaluator {
|
|
|
| if (initializerList != null) {
|
| for (Link<Node> link = initializerList.nodes;
|
| - !link.isEmpty;
|
| - link = link.tail) {
|
| + !link.isEmpty;
|
| + link = link.tail) {
|
| assert(link.head is Send);
|
| - if (link.head is !SendSet) {
|
| + if (link.head is! SendSet) {
|
| // A super initializer or constructor redirection.
|
| Send call = link.head;
|
| FunctionElement target = elements[call];
|
| - List<AstConstant> compiledArguments =
|
| - evaluateArgumentsToConstructor(
|
| - call, elements.getSelector(call).callStructure,
|
| - call.arguments, target,
|
| - compileArgument: evaluateConstant);
|
| + List<AstConstant> compiledArguments = evaluateArgumentsToConstructor(
|
| + call, elements.getSelector(call).callStructure, call.arguments,
|
| + target, compileArgument: evaluateConstant);
|
| evaluateSuperOrRedirectSend(compiledArguments, target);
|
| foundSuperOrRedirect = true;
|
| } else {
|
| @@ -1266,8 +1163,8 @@ class ConstructorEvaluator extends CompileTimeConstantEvaluator {
|
| // already and compilation will fail anyway. So just ignore that case.
|
| if (targetConstructor != null) {
|
| List<AstConstant> compiledArguments = evaluateArgumentsToConstructor(
|
| - functionNode, CallStructure.NO_ARGS,
|
| - const Link<Node>(), targetConstructor);
|
| + functionNode, CallStructure.NO_ARGS, const Link<Node>(),
|
| + targetConstructor);
|
| evaluateSuperOrRedirectSend(compiledArguments, targetConstructor);
|
| }
|
| }
|
| @@ -1291,22 +1188,24 @@ class ConstructorEvaluator extends CompileTimeConstantEvaluator {
|
| /// inheritance chain of [classElement].
|
| Map<FieldElement, AstConstant> buildFieldConstants(
|
| ClassElement classElement) {
|
| - Map<FieldElement, AstConstant> fieldConstants =
|
| - <FieldElement, AstConstant>{};
|
| - classElement.implementation.forEachInstanceField(
|
| - (ClassElement enclosing, FieldElement field) {
|
| - AstConstant fieldValue = fieldValues[field];
|
| - if (fieldValue == null) {
|
| - // Use the default value.
|
| - ConstantExpression fieldExpression = handler.compileConstant(field);
|
| - fieldValue = new AstConstant.fromDefaultValue(
|
| - field,
|
| - fieldExpression,
|
| - handler.getConstantValue(fieldExpression));
|
| - }
|
| - fieldConstants[field] = fieldValue;
|
| - },
|
| - includeSuperAndInjectedMembers: true);
|
| + Map<FieldElement, AstConstant> fieldConstants = <FieldElement, AstConstant>{
|
| + };
|
| + classElement.implementation
|
| + .forEachInstanceField((ClassElement enclosing, FieldElement field) {
|
| + AstConstant fieldValue = fieldValues[field];
|
| + if (fieldValue == null) {
|
| + // Use the default value.
|
| + ConstantExpression fieldExpression =
|
| + handler.internalCompileVariable(field, true, false);
|
| + fieldValue = new AstConstant.fromDefaultValue(
|
| + field, fieldExpression, handler.getConstantValue(fieldExpression));
|
| + // TODO(het): If the field value doesn't typecheck due to the type
|
| + // variable in the constructor invocation, then report the error on the
|
| + // invocation rather than the field.
|
| + potentiallyCheckType(field, fieldValue);
|
| + }
|
| + fieldConstants[field] = fieldValue;
|
| + }, includeSuperAndInjectedMembers: true);
|
| return fieldConstants;
|
| }
|
| }
|
| @@ -1328,15 +1227,11 @@ class AstConstant {
|
|
|
| AstConstant(this.element, this.node, this.expression, this.value);
|
|
|
| - factory AstConstant.fromDefaultValue(
|
| - VariableElement element,
|
| - ConstantExpression constant,
|
| - ConstantValue value) {
|
| - return new AstConstant(
|
| - element,
|
| - element.initializer != null ? element.initializer : element.node,
|
| - constant,
|
| - value);
|
| + factory AstConstant.fromDefaultValue(VariableElement element,
|
| + ConstantExpression constant, ConstantValue value) {
|
| + return new AstConstant(element, element.initializer != null
|
| + ? element.initializer
|
| + : element.node, constant, value);
|
| }
|
|
|
| String toString() => expression.toString();
|
| @@ -1344,8 +1239,7 @@ class AstConstant {
|
|
|
| /// A synthetic constant used to recover from errors.
|
| class ErroneousAstConstant extends AstConstant {
|
| - ErroneousAstConstant(Element element, Node node)
|
| - : super(element, node,
|
| + ErroneousAstConstant(Element element, Node node) : super(element, node,
|
| // TODO(johnniwinther): Return a [NonConstantValue] instead.
|
| new ErroneousConstantExpression(), new NullConstantValue());
|
| }
|
|
|