| Index: pkg/compiler/lib/src/resolution/members.dart
|
| diff --git a/pkg/compiler/lib/src/resolution/members.dart b/pkg/compiler/lib/src/resolution/members.dart
|
| index 6069d4cebddd98b67bb58ae935ed13eebc690f1b..fb0d246658580d7499c3d75516d40ca3d644c2e8 100644
|
| --- a/pkg/compiler/lib/src/resolution/members.dart
|
| +++ b/pkg/compiler/lib/src/resolution/members.dart
|
| @@ -102,6 +102,8 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| inCatchBlock = false,
|
| super(compiler, registry);
|
|
|
| + CoreTypes get coreTypes => compiler.coreTypes;
|
| +
|
| AsyncMarker get currentAsyncMarker {
|
| if (enclosingElement is FunctionElement) {
|
| FunctionElement function = enclosingElement;
|
| @@ -166,8 +168,8 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| return result;
|
| }
|
|
|
| - visitInStaticContext(Node node) {
|
| - inStaticContext(() => visit(node));
|
| + ResolutionResult visitInStaticContext(Node node) {
|
| + return inStaticContext(() => visit(node));
|
| }
|
|
|
| ErroneousElement reportAndCreateErroneousElement(
|
| @@ -230,7 +232,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| if (!inInstanceContext) {
|
| error(node, MessageKind.NO_INSTANCE_AVAILABLE, {'name': node});
|
| }
|
| - return null;
|
| + return const NoneResult();
|
| } else if (node.isSuper()) {
|
| if (!inInstanceContext) {
|
| error(node, MessageKind.NO_SUPER_IN_STATIC);
|
| @@ -238,7 +240,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| if ((ElementCategory.SUPER & allowedCategory) == 0) {
|
| error(node, MessageKind.INVALID_USE_OF_SUPER);
|
| }
|
| - return null;
|
| + return const NoneResult();
|
| } else {
|
| String name = node.source;
|
| Element element = lookupInScope(compiler, node, scope, name);
|
| @@ -272,7 +274,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| }
|
| }
|
|
|
| - ResolutionResult visitTypeAnnotation(TypeAnnotation node) {
|
| + TypeResult visitTypeAnnotation(TypeAnnotation node) {
|
| DartType type = resolveTypeAnnotation(node);
|
| if (inCheckContext) {
|
| registry.registerIsCheck(type);
|
| @@ -358,19 +360,17 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| }
|
| }
|
|
|
| - visitCascade(Cascade node) {
|
| + ResolutionResult visitCascade(Cascade node) {
|
| visit(node.expression);
|
| + return const NoneResult();
|
| }
|
|
|
| - visitCascadeReceiver(CascadeReceiver node) {
|
| + ResolutionResult visitCascadeReceiver(CascadeReceiver node) {
|
| visit(node.expression);
|
| + return const NoneResult();
|
| }
|
|
|
| - visitClassNode(ClassNode node) {
|
| - internalError(node, "shouldn't be called");
|
| - }
|
| -
|
| - visitIn(Node node, Scope nestedScope) {
|
| + ResolutionResult visitIn(Node node, Scope nestedScope) {
|
| Scope oldScope = scope;
|
| scope = nestedScope;
|
| ResolutionResult result = visit(node);
|
| @@ -382,7 +382,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| * Introduces new default targets for break and continue
|
| * before visiting the body of the loop
|
| */
|
| - visitLoopBodyIn(Loop loop, Node body, Scope bodyScope) {
|
| + void visitLoopBodyIn(Loop loop, Node body, Scope bodyScope) {
|
| JumpTarget element = getOrDefineTarget(loop);
|
| statementScope.enterLoop(element);
|
| visitIn(body, bodyScope);
|
| @@ -392,35 +392,42 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| }
|
| }
|
|
|
| - visitBlock(Block node) {
|
| + ResolutionResult visitBlock(Block node) {
|
| visitIn(node.statements, new BlockScope(scope));
|
| + return const NoneResult();
|
| }
|
|
|
| - visitDoWhile(DoWhile node) {
|
| + ResolutionResult visitDoWhile(DoWhile node) {
|
| visitLoopBodyIn(node, node.body, new BlockScope(scope));
|
| visit(node.condition);
|
| + return const NoneResult();
|
| }
|
|
|
| - visitEmptyStatement(EmptyStatement node) { }
|
| + ResolutionResult visitEmptyStatement(EmptyStatement node) {
|
| + return const NoneResult();
|
| + }
|
|
|
| - visitExpressionStatement(ExpressionStatement node) {
|
| + ResolutionResult visitExpressionStatement(ExpressionStatement node) {
|
| ExpressionStatement oldExpressionStatement = currentExpressionStatement;
|
| currentExpressionStatement = node;
|
| visit(node.expression);
|
| currentExpressionStatement = oldExpressionStatement;
|
| + return const NoneResult();
|
| }
|
|
|
| - visitFor(For node) {
|
| + ResolutionResult visitFor(For node) {
|
| Scope blockScope = new BlockScope(scope);
|
| visitIn(node.initializer, blockScope);
|
| visitIn(node.condition, blockScope);
|
| visitIn(node.update, blockScope);
|
| visitLoopBodyIn(node, node.body, blockScope);
|
| + return const NoneResult();
|
| }
|
|
|
| - visitFunctionDeclaration(FunctionDeclaration node) {
|
| + ResolutionResult visitFunctionDeclaration(FunctionDeclaration node) {
|
| assert(node.function.name != null);
|
| visitFunctionExpression(node.function, inFunctionDeclaration: true);
|
| + return const NoneResult();
|
| }
|
|
|
|
|
| @@ -431,8 +438,9 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| ///
|
| /// This is used to distinguish local function declarations from anonymous
|
| /// function expressions.
|
| - visitFunctionExpression(FunctionExpression node,
|
| - {bool inFunctionDeclaration: false}) {
|
| + ResolutionResult visitFunctionExpression(
|
| + FunctionExpression node,
|
| + {bool inFunctionDeclaration: false}) {
|
| bool doAddToScope = inFunctionDeclaration;
|
| if (!inFunctionDeclaration && node.name != null) {
|
| compiler.reportError(
|
| @@ -480,13 +488,15 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
|
|
| registry.registerClosure(function);
|
| registry.registerInstantiatedClass(compiler.functionClass);
|
| + return const NoneResult();
|
| }
|
|
|
| - visitIf(If node) {
|
| + ResolutionResult visitIf(If node) {
|
| doInPromotionScope(node.condition.expression, () => visit(node.condition));
|
| doInPromotionScope(node.thenPart,
|
| () => visitIn(node.thenPart, new BlockScope(scope)));
|
| visitIn(node.elsePart, new BlockScope(scope));
|
| + return const NoneResult();
|
| }
|
|
|
| ResolutionResult resolveSend(Send node) {
|
| @@ -533,26 +543,26 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| // TODO(ahe): Why is this using GENERIC?
|
| error(node.selector, MessageKind.GENERIC,
|
| {'text': "expected an identifier"});
|
| - return null;
|
| + return const NoneResult();
|
| } else if (node.isSuperCall) {
|
| if (node.isOperator) {
|
| if (isUserDefinableOperator(name)) {
|
| name = selector.name;
|
| } else {
|
| error(node.selector, MessageKind.ILLEGAL_SUPER_SEND, {'name': name});
|
| - return null;
|
| + return const NoneResult();
|
| }
|
| }
|
| if (!inInstanceContext) {
|
| error(node.receiver, MessageKind.NO_INSTANCE_AVAILABLE, {'name': name});
|
| - return null;
|
| + return const NoneResult();
|
| }
|
| if (currentClass.supertype == null) {
|
| // This is just to guard against internal errors, so no need
|
| // for a real error message.
|
| error(node.receiver, MessageKind.GENERIC,
|
| {'text': "Object has no superclass"});
|
| - return null;
|
| + return const NoneResult();
|
| }
|
| // TODO(johnniwinther): Ensure correct behavior if currentClass is a
|
| // patch.
|
| @@ -569,9 +579,8 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| registry.registerDynamicInvocation(selector);
|
| registry.registerSuperNoSuchMethod();
|
| }
|
| - } else if (resolvedReceiver == null ||
|
| - Elements.isUnresolved(resolvedReceiver.element)) {
|
| - return null;
|
| + } else if (Elements.isUnresolved(resolvedReceiver.element)) {
|
| + return const NoneResult();
|
| } else if (resolvedReceiver.element.isClass) {
|
| ClassElement receiverClass = resolvedReceiver.element;
|
| receiverClass.ensureResolved(compiler);
|
| @@ -582,7 +591,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| // The following code that looks up the selector on the resolved
|
| // receiver will treat the second as the invocation of a static operator
|
| // if the resolved receiver is not null.
|
| - return null;
|
| + return const NoneResult();
|
| }
|
| MembersCreator.computeClassMembersByName(
|
| compiler, receiverClass.declaration, name);
|
| @@ -630,7 +639,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| classElement.ensureResolved(compiler);
|
| }
|
| }
|
| - return new ElementResult(target);
|
| + return new ResolutionResult.forElement(target);
|
| }
|
|
|
| static Selector computeSendSelector(Send node,
|
| @@ -897,7 +906,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| }
|
| registry.registerIsCheck(type);
|
| registry.registerSendStructure(node, sendStructure);
|
| - return null;
|
| + return const NoneResult();
|
| }
|
|
|
| /// Handle a type cast expression, like `a as T`.
|
| @@ -909,7 +918,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| DartType type = resolveTypeAnnotation(typeNode);
|
| registry.registerAsCheck(type);
|
| registry.registerSendStructure(node, new AsStructure(type));
|
| - return null;
|
| + return const NoneResult();
|
| }
|
|
|
| /// Handle the unary expression of an unresolved unary operator [text], like
|
| @@ -923,12 +932,13 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| }
|
|
|
| registry.registerSendStructure(node, const InvalidUnaryStructure());
|
| - return null;
|
| + return const NoneResult();
|
| }
|
|
|
| /// Handle the unary expression of a user definable unary [operator], like
|
| /// `-a`, and `-super`.
|
| ResolutionResult handleUserDefinableUnary(Send node, UnaryOperator operator) {
|
| + ResolutionResult result = const NoneResult();
|
| Node expression = node.receiver;
|
| Selector selector = operator.selector;
|
| // TODO(johnniwinther): Remove this when all information goes through the
|
| @@ -949,9 +959,38 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| registry.useElement(node, semantics.element);
|
| }
|
| } else {
|
| - visitExpression(expression);
|
| + ResolutionResult expressionResult = visitExpression(expression);
|
| semantics = new DynamicAccess.dynamicProperty(expression);
|
| registry.registerDynamicInvocation(selector);
|
| +
|
| + if (expressionResult.isConstant) {
|
| + bool isValidConstant;
|
| + ConstantExpression expressionConstant = expressionResult.constant;
|
| + DartType knownExpressionType =
|
| + expressionConstant.getKnownType(coreTypes);
|
| + switch (operator.kind) {
|
| + case UnaryOperatorKind.COMPLEMENT:
|
| + isValidConstant =
|
| + knownExpressionType == coreTypes.intType;
|
| + break;
|
| + case UnaryOperatorKind.NEGATE:
|
| + isValidConstant =
|
| + knownExpressionType == coreTypes.intType ||
|
| + knownExpressionType == coreTypes.doubleType;
|
| + break;
|
| + case UnaryOperatorKind.NOT:
|
| + internalError(node,
|
| + "Unexpected user definable unary operator: $operator");
|
| + }
|
| + if (isValidConstant) {
|
| + // TODO(johnniwinther): Handle potentially invalid constant
|
| + // expressions.
|
| + ConstantExpression constant =
|
| + new UnaryConstantExpression(operator, expressionConstant);
|
| + registry.setConstant(node, constant);
|
| + result = new ConstantResult(node, constant);
|
| + }
|
| + }
|
| }
|
| if (semantics != null) {
|
| // TODO(johnniwinther): Support invalid super access as an
|
| @@ -959,7 +998,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| registry.registerSendStructure(node,
|
| new UnaryStructure(semantics, operator));
|
| }
|
| - return null;
|
| + return result;
|
| }
|
|
|
| /// Handle a not expression, like `!a`.
|
| @@ -967,30 +1006,75 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| assert(invariant(node, operator.kind == UnaryOperatorKind.NOT));
|
|
|
| Node expression = node.receiver;
|
| - visitExpression(expression);
|
| + ResolutionResult result = visitExpression(expression);
|
| registry.registerSendStructure(node,
|
| new NotStructure(new DynamicAccess.dynamicProperty(expression)));
|
| - return null;
|
| +
|
| + if (result.isConstant) {
|
| + ConstantExpression expressionConstant = result.constant;
|
| + if (expressionConstant.getKnownType(coreTypes) == coreTypes.boolType) {
|
| + // TODO(johnniwinther): Handle potentially invalid constant expressions.
|
| + ConstantExpression constant =
|
| + new UnaryConstantExpression(operator, expressionConstant);
|
| + registry.setConstant(node, constant);
|
| + return new ConstantResult(node, constant);
|
| + }
|
| + }
|
| +
|
| + return const NoneResult();
|
| }
|
|
|
| /// Handle a logical and expression, like `a && b`.
|
| ResolutionResult handleLogicalAnd(Send node) {
|
| Node left = node.receiver;
|
| Node right = node.arguments.head;
|
| - doInPromotionScope(left, () => visitExpression(left));
|
| - doInPromotionScope(right, () => visitExpression(right));
|
| + ResolutionResult leftResult =
|
| + doInPromotionScope(left, () => visitExpression(left));
|
| + ResolutionResult rightResult =
|
| + doInPromotionScope(right, () => visitExpression(right));
|
| registry.registerSendStructure(node, const LogicalAndStructure());
|
| - return null;
|
| +
|
| + if (leftResult.isConstant && rightResult.isConstant) {
|
| + ConstantExpression leftConstant = leftResult.constant;
|
| + ConstantExpression rightConstant = rightResult.constant;
|
| + if (leftConstant.getKnownType(coreTypes) == coreTypes.boolType &&
|
| + rightConstant.getKnownType(coreTypes) == coreTypes.boolType) {
|
| + // TODO(johnniwinther): Handle potentially invalid constant expressions.
|
| + ConstantExpression constant = new BinaryConstantExpression(
|
| + leftConstant,
|
| + BinaryOperator.LOGICAL_AND,
|
| + rightConstant);
|
| + registry.setConstant(node, constant);
|
| + return new ConstantResult(node, constant);
|
| + }
|
| + }
|
| +
|
| + return const NoneResult();
|
| }
|
|
|
| /// Handle a logical or expression, like `a || b`.
|
| ResolutionResult handleLogicalOr(Send node) {
|
| Node left = node.receiver;
|
| Node right = node.arguments.head;
|
| - visitExpression(left);
|
| - visitExpression(right);
|
| + ResolutionResult leftResult = visitExpression(left);
|
| + ResolutionResult rightResult = visitExpression(right);
|
| registry.registerSendStructure(node, const LogicalOrStructure());
|
| - return null;
|
| +
|
| + if (leftResult.isConstant && rightResult.isConstant) {
|
| + ConstantExpression leftConstant = leftResult.constant;
|
| + ConstantExpression rightConstant = rightResult.constant;
|
| + if (leftConstant.getKnownType(coreTypes) == coreTypes.boolType &&
|
| + rightConstant.getKnownType(coreTypes) == coreTypes.boolType) {
|
| + // TODO(johnniwinther): Handle potentially invalid constant expressions.
|
| + ConstantExpression constant = new BinaryConstantExpression(
|
| + leftConstant,
|
| + BinaryOperator.LOGICAL_OR,
|
| + rightConstant);
|
| + registry.setConstant(node, constant);
|
| + return new ConstantResult(node, constant);
|
| + }
|
| + }
|
| + return const NoneResult();
|
| }
|
|
|
| /// Handle an if-null expression, like `a ?? b`.
|
| @@ -1000,7 +1084,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| visitExpression(left);
|
| visitExpression(right);
|
| registry.registerSendStructure(node, const IfNullStructure());
|
| - return null;
|
| + return const NoneResult();
|
| }
|
|
|
| /// Handle the binary expression of an unresolved binary operator [text], like
|
| @@ -1015,13 +1099,14 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| }
|
| visitExpression(right);
|
| registry.registerSendStructure(node, const InvalidBinaryStructure());
|
| - return null;
|
| + return const NoneResult();
|
| }
|
|
|
| /// Handle the binary expression of a user definable binary [operator], like
|
| /// `a + b`, `super + b`, `a == b` and `a != b`.
|
| ResolutionResult handleUserDefinableBinary(Send node,
|
| BinaryOperator operator) {
|
| + ResolutionResult result = const NoneResult();
|
| Node left = node.receiver;
|
| Node right = node.arguments.head;
|
| AccessSemantics semantics;
|
| @@ -1047,12 +1132,88 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| // the [SendStructure].
|
| registry.useElement(node, semantics.element);
|
| }
|
| + visitExpression(right);
|
| } else {
|
| - visitExpression(left);
|
| + ResolutionResult leftResult = visitExpression(left);
|
| + ResolutionResult rightResult = visitExpression(right);
|
| registry.registerDynamicInvocation(selector);
|
| semantics = new DynamicAccess.dynamicProperty(left);
|
| +
|
| + if (leftResult.isConstant && rightResult.isConstant) {
|
| + bool isValidConstant;
|
| + ConstantExpression leftConstant = leftResult.constant;
|
| + ConstantExpression rightConstant = leftResult.constant;
|
| + DartType knownLeftType = leftConstant.getKnownType(coreTypes);
|
| + DartType knownRightType = rightConstant.getKnownType(coreTypes);
|
| + switch (operator.kind) {
|
| + case BinaryOperatorKind.EQ:
|
| + case BinaryOperatorKind.NOT_EQ:
|
| + isValidConstant =
|
| + (knownLeftType == coreTypes.intType ||
|
| + knownLeftType == coreTypes.doubleType ||
|
| + knownLeftType == coreTypes.stringType ||
|
| + knownLeftType == coreTypes.boolType ||
|
| + knownLeftType == coreTypes.nullType) &&
|
| + (knownRightType == coreTypes.intType ||
|
| + knownRightType == coreTypes.doubleType ||
|
| + knownRightType == coreTypes.stringType ||
|
| + knownRightType == coreTypes.boolType ||
|
| + knownRightType == coreTypes.nullType);
|
| + break;
|
| + case BinaryOperatorKind.ADD:
|
| + isValidConstant =
|
| + (knownLeftType == coreTypes.intType ||
|
| + knownLeftType == coreTypes.doubleType ||
|
| + knownLeftType == coreTypes.stringType) &&
|
| + (knownRightType == coreTypes.intType ||
|
| + knownRightType == coreTypes.doubleType ||
|
| + knownRightType == coreTypes.stringType);
|
| + break;
|
| + case BinaryOperatorKind.SUB:
|
| + case BinaryOperatorKind.MUL:
|
| + case BinaryOperatorKind.DIV:
|
| + case BinaryOperatorKind.IDIV:
|
| + case BinaryOperatorKind.MOD:
|
| + case BinaryOperatorKind.GTEQ:
|
| + case BinaryOperatorKind.GT:
|
| + case BinaryOperatorKind.LTEQ:
|
| + case BinaryOperatorKind.LT:
|
| + isValidConstant =
|
| + (knownLeftType == coreTypes.intType ||
|
| + knownLeftType == coreTypes.doubleType) &&
|
| + (knownRightType == coreTypes.intType ||
|
| + knownRightType == coreTypes.doubleType);
|
| + break;
|
| + case BinaryOperatorKind.SHL:
|
| + case BinaryOperatorKind.SHR:
|
| + case BinaryOperatorKind.AND:
|
| + case BinaryOperatorKind.OR:
|
| + case BinaryOperatorKind.XOR:
|
| + isValidConstant =
|
| + knownLeftType == coreTypes.intType &&
|
| + knownRightType == coreTypes.intType;
|
| + break;
|
| + case BinaryOperatorKind.INDEX:
|
| + isValidConstant = false;
|
| + break;
|
| + case BinaryOperatorKind.LOGICAL_AND:
|
| + case BinaryOperatorKind.LOGICAL_OR:
|
| + case BinaryOperatorKind.IF_NULL:
|
| + internalError(node, "Unexpected binary operator '${operator}'.");
|
| + break;
|
| + }
|
| + if (isValidConstant) {
|
| + // TODO(johnniwinther): Handle potentially invalid constant
|
| + // expressions.
|
| + ConstantExpression constant = new BinaryConstantExpression(
|
| + leftResult.constant,
|
| + operator,
|
| + rightResult.constant);
|
| + registry.setConstant(node, constant);
|
| + result = new ConstantResult(node, constant);
|
| + }
|
| + }
|
| }
|
| - visitExpression(right);
|
|
|
| if (semantics != null) {
|
| // TODO(johnniwinther): Support invalid super access as an
|
| @@ -1093,7 +1254,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| }
|
| registry.registerSendStructure(node, sendStructure);
|
| }
|
| - return null;
|
| + return result;
|
| }
|
|
|
| /// Handle an invocation of an expression, like `(){}()` or `(foo)()`.
|
| @@ -1110,7 +1271,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| registry.registerDynamicInvocation(selector);
|
| registry.registerSendStructure(node,
|
| new InvokeStructure(new AccessSemantics.expression(), selector));
|
| - return null;
|
| + return const NoneResult();
|
| }
|
|
|
| /// Handle a, possibly invalid, assertion, like `assert(cond)` or `assert()`.
|
| @@ -1162,7 +1323,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| // TODO(johnniwinther): Remove this when all information goes through
|
| // the [SendStructure].
|
| registry.setSelector(node, selector);
|
| - return null;
|
| + return const NoneResult();
|
| }
|
|
|
| /// Handle access on `this`, like `this()` and `this` when it is parsed as a
|
| @@ -1186,7 +1347,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| // TODO(johnniwinther): Handle get of `this` when it is a [Send] node.
|
| internalError(node, "Unexpected node '$node'.");
|
| }
|
| - return null;
|
| + return const NoneResult();
|
| }
|
|
|
| /// Handle access of a super property, like `super.foo` and `super.foo()`.
|
| @@ -1265,7 +1426,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| // the [SendStructure].
|
| registry.useElement(node, target);
|
| registry.setSelector(node, selector);
|
| - return null;
|
| + return const NoneResult();
|
| }
|
|
|
| /// Handle a [Send] whose selector is an [Operator], like `a && b`, `a is T`,
|
| @@ -1341,7 +1502,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| }
|
| // TODO(johnniwinther): Handle invalid this access as an
|
| // [AccessSemantics].
|
| - return null;
|
| + return const NoneResult();
|
| }
|
| // TODO(johnniwinther): Handle remaining qualified sends.
|
| return oldVisitSend(node);
|
| @@ -1372,7 +1533,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| registry.setSelector(node, selector);
|
| registry.useElement(node, element);
|
| registry.registerSendStructure(node, sendStructure);
|
| - return null;
|
| + return const NoneResult();
|
| }
|
|
|
| /// Handle an unqualified [Send], that is where the `node.receiver` is null,
|
| @@ -1429,7 +1590,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| ResolutionResult result = resolveSend(node);
|
| sendIsMemberAccess = oldSendIsMemberAccess;
|
|
|
| - Element target = result != null ? result.element : null;
|
| + Element target = result.element;
|
|
|
| if (target != null
|
| && target == compiler.mirrorSystemGetNameFunction
|
| @@ -1482,7 +1643,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| // If the selector is null, it means that we will not be generating
|
| // code for this as a send.
|
| Selector selector = registry.getSelector(node);
|
| - if (selector == null) return null;
|
| + if (selector == null) return const NoneResult();
|
|
|
| if (node.isCall) {
|
| if (Elements.isUnresolved(target) ||
|
| @@ -1535,7 +1696,8 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| if (node.isPropertyAccess && Elements.isStaticOrTopLevelFunction(target)) {
|
| registry.registerGetOfStaticFunction(target.declaration);
|
| }
|
| - return node.isPropertyAccess ? new ElementResult(target) : null;
|
| + return node.isPropertyAccess
|
| + ? new ResolutionResult.forElement(target) : const NoneResult();
|
| }
|
|
|
| /// Callback for native enqueuer to parse a type. Returns [:null:] on error.
|
| @@ -1553,7 +1715,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| sendIsMemberAccess = node.isPropertyAccess || node.isCall;
|
| ResolutionResult result = resolveSend(node);
|
| sendIsMemberAccess = oldSendIsMemberAccess;
|
| - Element target = result != null ? result.element : null;
|
| + Element target = result.element;
|
| Element setter = target;
|
| Element getter = target;
|
| String operatorName = node.assignmentOperator.source;
|
| @@ -1677,7 +1839,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| }
|
|
|
| registerSend(selector, setter);
|
| - return new ElementResult(registry.useElement(node, setter));
|
| + return new ResolutionResult.forElement(registry.useElement(node, setter));
|
| }
|
|
|
| void registerSend(Selector selector, Element target) {
|
| @@ -1700,60 +1862,90 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| }
|
| }
|
|
|
| - visitLiteralInt(LiteralInt node) {
|
| - registry.registerInstantiatedClass(compiler.intClass);
|
| + ConstantResult visitLiteralInt(LiteralInt node) {
|
| + registry.registerInstantiatedType(coreTypes.intType);
|
| + ConstantExpression constant = new IntConstantExpression(node.value);
|
| + registry.setConstant(node, constant);
|
| + return new ConstantResult(node, constant);
|
| }
|
|
|
| - visitLiteralDouble(LiteralDouble node) {
|
| - registry.registerInstantiatedClass(compiler.doubleClass);
|
| + ConstantResult visitLiteralDouble(LiteralDouble node) {
|
| + registry.registerInstantiatedType(coreTypes.doubleType);
|
| + ConstantExpression constant = new DoubleConstantExpression(node.value);
|
| + registry.setConstant(node, constant);
|
| + return new ConstantResult(node, constant);
|
| }
|
|
|
| - visitLiteralBool(LiteralBool node) {
|
| - registry.registerInstantiatedClass(compiler.boolClass);
|
| + ConstantResult visitLiteralBool(LiteralBool node) {
|
| + registry.registerInstantiatedType(coreTypes.boolType);
|
| + ConstantExpression constant = new BoolConstantExpression(node.value);
|
| + registry.setConstant(node, constant);
|
| + return new ConstantResult(node, constant);
|
| }
|
|
|
| - visitLiteralString(LiteralString node) {
|
| - registry.registerInstantiatedClass(compiler.stringClass);
|
| + ResolutionResult visitLiteralString(LiteralString node) {
|
| + registry.registerInstantiatedType(coreTypes.stringType);
|
| + if (node.dartString != null) {
|
| + // [dartString] might be null on parser errors.
|
| + ConstantExpression constant =
|
| + new StringConstantExpression(node.dartString.slowToString());
|
| + registry.setConstant(node, constant);
|
| + return new ConstantResult(node, constant);
|
| + }
|
| + return const NoneResult();
|
| }
|
|
|
| - visitLiteralNull(LiteralNull node) {
|
| - registry.registerInstantiatedClass(compiler.nullClass);
|
| + ConstantResult visitLiteralNull(LiteralNull node) {
|
| + registry.registerInstantiatedType(coreTypes.nullType);
|
| + ConstantExpression constant = new NullConstantExpression();
|
| + registry.setConstant(node, constant);
|
| + return new ConstantResult(node, constant);
|
| }
|
|
|
| - visitLiteralSymbol(LiteralSymbol node) {
|
| + ConstantResult visitLiteralSymbol(LiteralSymbol node) {
|
| registry.registerInstantiatedClass(compiler.symbolClass);
|
| registry.registerStaticUse(compiler.symbolConstructor.declaration);
|
| - registry.registerConstSymbol(node.slowNameString);
|
| - if (!validateSymbol(node, node.slowNameString, reportError: false)) {
|
| + String name = node.slowNameString;
|
| + registry.registerConstSymbol(name);
|
| + if (!validateSymbol(node, name, reportError: false)) {
|
| compiler.reportError(node,
|
| MessageKind.UNSUPPORTED_LITERAL_SYMBOL,
|
| - {'value': node.slowNameString});
|
| + {'value': name});
|
| }
|
| analyzeConstantDeferred(node);
|
| + ConstantExpression constant = new SymbolConstantExpression(name);
|
| + registry.setConstant(node, constant);
|
| + return new ConstantResult(node, constant);
|
| }
|
|
|
| - visitStringJuxtaposition(StringJuxtaposition node) {
|
| - registry.registerInstantiatedClass(compiler.stringClass);
|
| - node.visitChildren(this);
|
| + ResolutionResult visitStringJuxtaposition(StringJuxtaposition node) {
|
| + registry.registerInstantiatedType(coreTypes.stringType);
|
| + ResolutionResult first = visit(node.first);
|
| + ResolutionResult second = visit(node.second);
|
| + if (first.isConstant && second.isConstant) {
|
| + ConstantExpression constant = new ConcatenateConstantExpression(
|
| + <ConstantExpression>[first.constant, second.constant]);
|
| + registry.setConstant(node, constant);
|
| + return new ConstantResult(node, constant);
|
| + }
|
| + return const NoneResult();
|
| }
|
|
|
| - visitNodeList(NodeList node) {
|
| + ResolutionResult visitNodeList(NodeList node) {
|
| for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) {
|
| visit(link.head);
|
| }
|
| + return const NoneResult();
|
| }
|
|
|
| - visitOperator(Operator node) {
|
| - internalError(node, 'operator');
|
| - }
|
| -
|
| - visitRethrow(Rethrow node) {
|
| + ResolutionResult visitRethrow(Rethrow node) {
|
| if (!inCatchBlock) {
|
| error(node, MessageKind.THROW_WITHOUT_EXPRESSION);
|
| }
|
| + return const NoneResult();
|
| }
|
|
|
| - visitReturn(Return node) {
|
| + ResolutionResult visitReturn(Return node) {
|
| Node expression = node.expression;
|
| if (expression != null) {
|
| if (enclosingElement.isGenerativeConstructor) {
|
| @@ -1770,15 +1962,17 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| }
|
| }
|
| visit(node.expression);
|
| + return const NoneResult();
|
| }
|
|
|
| - visitYield(Yield node) {
|
| + ResolutionResult visitYield(Yield node) {
|
| compiler.streamClass.ensureResolved(compiler);
|
| compiler.iterableClass.ensureResolved(compiler);
|
| visit(node.expression);
|
| + return const NoneResult();
|
| }
|
|
|
| - visitRedirectingFactoryBody(RedirectingFactoryBody node) {
|
| + ResolutionResult visitRedirectingFactoryBody(RedirectingFactoryBody node) {
|
| final isSymbolConstructor = enclosingElement == compiler.symbolConstructor;
|
| if (!enclosingElement.isFactoryConstructor) {
|
| compiler.reportError(
|
| @@ -1802,7 +1996,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| registry.setRedirectingTargetConstructor(node, redirectionTarget);
|
| if (Elements.isUnresolved(redirectionTarget)) {
|
| registry.registerThrowNoSuchMethod();
|
| - return;
|
| + return const NoneResult();
|
| } else {
|
| if (isConstConstructor &&
|
| !redirectionTarget.isConst) {
|
| @@ -1848,19 +2042,22 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| if (isSymbolConstructor) {
|
| registry.registerSymbolConstructor();
|
| }
|
| + return const NoneResult();
|
| }
|
|
|
| - visitThrow(Throw node) {
|
| + ResolutionResult visitThrow(Throw node) {
|
| registry.registerThrowExpression();
|
| visit(node.expression);
|
| + return const NoneResult();
|
| }
|
|
|
| - visitAwait(Await node) {
|
| + ResolutionResult visitAwait(Await node) {
|
| compiler.futureClass.ensureResolved(compiler);
|
| visit(node.expression);
|
| + return const NoneResult();
|
| }
|
|
|
| - visitVariableDefinitions(VariableDefinitions node) {
|
| + ResolutionResult visitVariableDefinitions(VariableDefinitions node) {
|
| DartType type;
|
| if (node.type != null) {
|
| type = resolveTypeAnnotation(node.type);
|
| @@ -1905,22 +2102,28 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| compiler.resolver.resolveMetadata(enclosingElement, node);
|
| }
|
| visitor.visit(node.definitions);
|
| + return const NoneResult();
|
| }
|
|
|
| - visitWhile(While node) {
|
| + ResolutionResult visitWhile(While node) {
|
| visit(node.condition);
|
| visitLoopBodyIn(node, node.body, new BlockScope(scope));
|
| + return const NoneResult();
|
| }
|
|
|
| - visitParenthesizedExpression(ParenthesizedExpression node) {
|
| + ResolutionResult visitParenthesizedExpression(ParenthesizedExpression node) {
|
| bool oldSendIsMemberAccess = sendIsMemberAccess;
|
| sendIsMemberAccess = false;
|
| var oldCategory = allowedCategory;
|
| allowedCategory = ElementCategory.VARIABLE | ElementCategory.FUNCTION
|
| | ElementCategory.IMPLIES_TYPE;
|
| - visit(node.expression);
|
| + ResolutionResult result = visit(node.expression);
|
| allowedCategory = oldCategory;
|
| sendIsMemberAccess = oldSendIsMemberAccess;
|
| + if (result.kind == ResultKind.CONSTANT) {
|
| + return result;
|
| + }
|
| + return const NoneResult();
|
| }
|
|
|
| ResolutionResult visitNewExpression(NewExpression node) {
|
| @@ -1933,7 +2136,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| resolveArguments(node.send.argumentsNode);
|
| registry.useElement(node.send, constructor);
|
| if (Elements.isUnresolved(constructor)) {
|
| - return new ElementResult(constructor);
|
| + return new ResolutionResult.forElement(constructor);
|
| }
|
| constructor.computeSignature(compiler);
|
| if (!callSelector.applies(constructor, compiler.world)) {
|
| @@ -1971,7 +2174,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| argumentNode, registry.mapping);
|
| ConstantValue name = compiler.constants.getConstantValue(constant);
|
| if (!name.isString) {
|
| - DartType type = name.getType(compiler.coreTypes);
|
| + DartType type = name.getType(coreTypes);
|
| compiler.reportError(argumentNode, MessageKind.STRING_EXPECTED,
|
| {'type': type});
|
| } else {
|
| @@ -1997,7 +2200,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| analyzeConstantDeferred(node);
|
| }
|
|
|
| - return null;
|
| + return const NoneResult();
|
| }
|
|
|
| void checkConstMapKeysDontOverrideEquals(Spannable spannable,
|
| @@ -2105,12 +2308,8 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| return type;
|
| }
|
|
|
| - visitModifiers(Modifiers node) {
|
| - internalError(node, 'modifiers');
|
| - }
|
| -
|
| - visitLiteralList(LiteralList node) {
|
| - bool oldSendIsMemberAccess = sendIsMemberAccess;
|
| + ResolutionResult visitLiteralList(LiteralList node) {
|
| + bool isValidAsConstant = true;
|
| sendIsMemberAccess = false;
|
|
|
| NodeList arguments = node.typeArguments;
|
| @@ -2120,6 +2319,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| if (nodes.isEmpty) {
|
| // The syntax [: <>[] :] is not allowed.
|
| error(arguments, MessageKind.MISSING_TYPE_ARGUMENT);
|
| + isValidAsConstant = false;
|
| } else {
|
| typeArgument = resolveTypeAnnotation(nodes.head);
|
| for (nodes = nodes.tail; !nodes.isEmpty; nodes = nodes.tail) {
|
| @@ -2133,47 +2333,98 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| if (node.isConst && typeArgument.containsTypeVariables) {
|
| compiler.reportError(arguments.nodes.head,
|
| MessageKind.TYPE_VARIABLE_IN_CONSTANT);
|
| + isValidAsConstant = false;
|
| }
|
| - listType = new InterfaceType(compiler.listClass, [typeArgument]);
|
| + listType = coreTypes.listType(typeArgument);
|
| } else {
|
| - compiler.listClass.computeType(compiler);
|
| - listType = compiler.listClass.rawType;
|
| + listType = coreTypes.listType();
|
| }
|
| registry.setType(node, listType);
|
| registry.registerInstantiatedType(listType);
|
| registry.registerRequiredType(listType, enclosingElement);
|
| - visit(node.elements);
|
| if (node.isConst) {
|
| + List<ConstantExpression> constantExpressions = <ConstantExpression>[];
|
| + for (Node element in node.elements) {
|
| + ResolutionResult elementResult = visit(element);
|
| + if (isValidAsConstant && elementResult.isConstant) {
|
| + constantExpressions.add(elementResult.constant);
|
| + } else {
|
| + isValidAsConstant = false;
|
| + }
|
| + }
|
| analyzeConstantDeferred(node);
|
| + sendIsMemberAccess = false;
|
| + if (isValidAsConstant) {
|
| + ConstantExpression constant =
|
| + new ListConstantExpression(listType, constantExpressions);
|
| + registry.setConstant(node, constant);
|
| + return new ConstantResult(node, constant);
|
| + }
|
| + } else {
|
| + visit(node.elements);
|
| + sendIsMemberAccess = false;
|
| }
|
| + return const NoneResult();
|
|
|
| - sendIsMemberAccess = false;
|
| }
|
|
|
| - visitConditional(Conditional node) {
|
| - doInPromotionScope(node.condition, () => visit(node.condition));
|
| - doInPromotionScope(node.thenExpression, () => visit(node.thenExpression));
|
| - visit(node.elseExpression);
|
| + ResolutionResult visitConditional(Conditional node) {
|
| + ResolutionResult conditionResult =
|
| + doInPromotionScope(node.condition, () => visit(node.condition));
|
| + ResolutionResult thenResult =
|
| + doInPromotionScope(node.thenExpression, () => visit(node.thenExpression));
|
| + ResolutionResult elseResult = visit(node.elseExpression);
|
| + if (conditionResult.isConstant &&
|
| + thenResult.isConstant &&
|
| + elseResult.isConstant) {
|
| + ConstantExpression constant = new ConditionalConstantExpression(
|
| + conditionResult.constant,
|
| + thenResult.constant,
|
| + elseResult.constant);
|
| + registry.setConstant(node, constant);
|
| + return new ConstantResult(node, constant);
|
| + }
|
| + return const NoneResult();
|
| }
|
|
|
| - visitStringInterpolation(StringInterpolation node) {
|
| - registry.registerInstantiatedClass(compiler.stringClass);
|
| + ResolutionResult visitStringInterpolation(StringInterpolation node) {
|
| + registry.registerInstantiatedType(coreTypes.stringType);
|
| registry.registerStringInterpolation();
|
| - node.visitChildren(this);
|
| - }
|
| -
|
| - visitStringInterpolationPart(StringInterpolationPart node) {
|
| registerImplicitInvocation('toString', 0);
|
| - node.visitChildren(this);
|
| +
|
| + bool isValidAsConstant = true;
|
| + List<ConstantExpression> parts = <ConstantExpression>[];
|
| +
|
| + void resolvePart(Node subnode) {
|
| + ResolutionResult result = visit(subnode);
|
| + if (isValidAsConstant && result.isConstant) {
|
| + parts.add(result.constant);
|
| + } else {
|
| + isValidAsConstant = false;
|
| + }
|
| + }
|
| +
|
| + resolvePart(node.string);
|
| + for (StringInterpolationPart part in node.parts) {
|
| + resolvePart(part.expression);
|
| + resolvePart(part.string);
|
| + }
|
| +
|
| + if (isValidAsConstant) {
|
| + ConstantExpression constant = new ConcatenateConstantExpression(parts);
|
| + registry.setConstant(node, constant);
|
| + return new ConstantResult(node, constant);
|
| + }
|
| + return const NoneResult();
|
| }
|
|
|
| - visitBreakStatement(BreakStatement node) {
|
| + ResolutionResult visitBreakStatement(BreakStatement node) {
|
| JumpTarget target;
|
| if (node.target == null) {
|
| target = statementScope.currentBreakTarget();
|
| if (target == null) {
|
| error(node, MessageKind.NO_BREAK_TARGET);
|
| - return;
|
| + return const NoneResult();
|
| }
|
| target.isBreakTarget = true;
|
| } else {
|
| @@ -2181,26 +2432,27 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| LabelDefinition label = statementScope.lookupLabel(labelName);
|
| if (label == null) {
|
| error(node.target, MessageKind.UNBOUND_LABEL, {'labelName': labelName});
|
| - return;
|
| + return const NoneResult();
|
| }
|
| target = label.target;
|
| if (!target.statement.isValidBreakTarget()) {
|
| error(node.target, MessageKind.INVALID_BREAK);
|
| - return;
|
| + return const NoneResult();
|
| }
|
| label.setBreakTarget();
|
| registry.useLabel(node, label);
|
| }
|
| registry.registerTargetOf(node, target);
|
| + return const NoneResult();
|
| }
|
|
|
| - visitContinueStatement(ContinueStatement node) {
|
| + ResolutionResult visitContinueStatement(ContinueStatement node) {
|
| JumpTarget target;
|
| if (node.target == null) {
|
| target = statementScope.currentContinueTarget();
|
| if (target == null) {
|
| error(node, MessageKind.NO_CONTINUE_TARGET);
|
| - return;
|
| + return const NoneResult();
|
| }
|
| target.isContinueTarget = true;
|
| } else {
|
| @@ -2208,7 +2460,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| LabelDefinition label = statementScope.lookupLabel(labelName);
|
| if (label == null) {
|
| error(node.target, MessageKind.UNBOUND_LABEL, {'labelName': labelName});
|
| - return;
|
| + return const NoneResult();
|
| }
|
| target = label.target;
|
| if (!target.statement.isValidContinueTarget()) {
|
| @@ -2218,6 +2470,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| registry.useLabel(node, label);
|
| }
|
| registry.registerTargetOf(node, target);
|
| + return const NoneResult();
|
| }
|
|
|
| registerImplicitInvocation(String name, int arity) {
|
| @@ -2225,7 +2478,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| registry.registerDynamicInvocation(selector);
|
| }
|
|
|
| - visitAsyncForIn(AsyncForIn node) {
|
| + ResolutionResult visitAsyncForIn(AsyncForIn node) {
|
| registry.registerAsyncForIn(node);
|
| registry.setCurrentSelector(node, compiler.currentSelector);
|
| registry.registerDynamicGetter(compiler.currentSelector);
|
| @@ -2237,9 +2490,10 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| Scope blockScope = new BlockScope(scope);
|
| visitForInDeclaredIdentifierIn(node.declaredIdentifier, node, blockScope);
|
| visitLoopBodyIn(node, node.body, blockScope);
|
| + return const NoneResult();
|
| }
|
|
|
| - visitSyncForIn(SyncForIn node) {
|
| + ResolutionResult visitSyncForIn(SyncForIn node) {
|
| registry.registerSyncForIn(node);
|
| registry.setIteratorSelector(node, compiler.iteratorSelector);
|
| registry.registerDynamicGetter(compiler.iteratorSelector);
|
| @@ -2253,10 +2507,13 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| Scope blockScope = new BlockScope(scope);
|
| visitForInDeclaredIdentifierIn(node.declaredIdentifier, node, blockScope);
|
| visitLoopBodyIn(node, node.body, blockScope);
|
| + return const NoneResult();
|
| }
|
|
|
| - visitForInDeclaredIdentifierIn(Node declaration, ForIn node,
|
| - Scope blockScope) {
|
| + void visitForInDeclaredIdentifierIn(
|
| + Node declaration,
|
| + ForIn node,
|
| + Scope blockScope) {
|
| LibraryElement library = enclosingElement.library;
|
|
|
| bool oldAllowFinalWithoutInitializer = allowFinalWithoutInitializer;
|
| @@ -2313,7 +2570,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| // Labels are handled by their containing statements/cases.
|
| }
|
|
|
| - visitLabeledStatement(LabeledStatement node) {
|
| + ResolutionResult visitLabeledStatement(LabeledStatement node) {
|
| Statement body = node.statement;
|
| JumpTarget targetElement = getOrDefineTarget(body);
|
| Map<String, LabelDefinition> labelElements = <String, LabelDefinition>{};
|
| @@ -2337,9 +2594,11 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| if (!targetElement.isTarget) {
|
| registry.undefineTarget(body);
|
| }
|
| + return const NoneResult();
|
| }
|
|
|
| - visitLiteralMap(LiteralMap node) {
|
| + ResolutionResult visitLiteralMap(LiteralMap node) {
|
| + bool isValidAsConstant = true;
|
| sendIsMemberAccess = false;
|
|
|
| NodeList arguments = node.typeArguments;
|
| @@ -2350,6 +2609,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| if (nodes.isEmpty) {
|
| // The syntax [: <>{} :] is not allowed.
|
| error(arguments, MessageKind.MISSING_TYPE_ARGUMENT);
|
| + isValidAsConstant = false;
|
| } else {
|
| keyTypeArgument = resolveTypeAnnotation(nodes.head);
|
| nodes = nodes.tail;
|
| @@ -2366,32 +2626,54 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| }
|
| DartType mapType;
|
| if (valueTypeArgument != null) {
|
| - mapType = new InterfaceType(compiler.mapClass,
|
| - [keyTypeArgument, valueTypeArgument]);
|
| + mapType = coreTypes.mapType(keyTypeArgument, valueTypeArgument);
|
| } else {
|
| - compiler.mapClass.computeType(compiler);
|
| - mapType = compiler.mapClass.rawType;
|
| + mapType = coreTypes.mapType();
|
| }
|
| if (node.isConst && mapType.containsTypeVariables) {
|
| compiler.reportError(arguments,
|
| MessageKind.TYPE_VARIABLE_IN_CONSTANT);
|
| + isValidAsConstant = false;
|
| }
|
| registry.registerMapLiteral(node, mapType, node.isConst);
|
| registry.registerRequiredType(mapType, enclosingElement);
|
| - node.visitChildren(this);
|
| if (node.isConst) {
|
| + List<ConstantExpression> keyExpressions = <ConstantExpression>[];
|
| + List<ConstantExpression> valueExpressions = <ConstantExpression>[];
|
| + for (LiteralMapEntry entry in node.entries) {
|
| + ResolutionResult keyResult = visit(entry.key);
|
| + ResolutionResult valueResult = visit(entry.value);
|
| + if (isValidAsConstant &&
|
| + keyResult.isConstant &&
|
| + valueResult.isConstant) {
|
| + keyExpressions.add(keyResult.constant);
|
| + valueExpressions.add(valueResult.constant);
|
| + } else {
|
| + isValidAsConstant = false;
|
| + }
|
| + }
|
| analyzeConstantDeferred(node);
|
| + sendIsMemberAccess = false;
|
| + if (isValidAsConstant) {
|
| + ConstantExpression constant = new MapConstantExpression(
|
| + mapType, keyExpressions, valueExpressions);
|
| + registry.setConstant(node, constant);
|
| + return new ConstantResult(node, constant);
|
| + }
|
| + } else {
|
| + node.visitChildren(this);
|
| + sendIsMemberAccess = false;
|
| }
|
| -
|
| - sendIsMemberAccess = false;
|
| + return const NoneResult();
|
| }
|
|
|
| - visitLiteralMapEntry(LiteralMapEntry node) {
|
| + ResolutionResult visitLiteralMapEntry(LiteralMapEntry node) {
|
| node.visitChildren(this);
|
| + return const NoneResult();
|
| }
|
|
|
| - visitNamedArgument(NamedArgument node) {
|
| - visit(node.expression);
|
| + ResolutionResult visitNamedArgument(NamedArgument node) {
|
| + return visit(node.expression);
|
| }
|
|
|
| DartType typeOfConstant(ConstantValue constant) {
|
| @@ -2476,7 +2758,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| }
|
| }
|
|
|
| - visitSwitchStatement(SwitchStatement node) {
|
| + ResolutionResult visitSwitchStatement(SwitchStatement node) {
|
| node.expression.accept(this);
|
|
|
| JumpTarget breakElement = getOrDefineTarget(node);
|
| @@ -2547,27 +2829,31 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| // TODO(15575): We should warn if we can detect a fall through
|
| // error.
|
| registry.registerFallThroughError();
|
| + return const NoneResult();
|
| }
|
|
|
| - visitSwitchCase(SwitchCase node) {
|
| + ResolutionResult visitSwitchCase(SwitchCase node) {
|
| node.labelsAndCases.accept(this);
|
| visitIn(node.statements, new BlockScope(scope));
|
| + return const NoneResult();
|
| }
|
|
|
| - visitCaseMatch(CaseMatch node) {
|
| + ResolutionResult visitCaseMatch(CaseMatch node) {
|
| visit(node.expression);
|
| + return const NoneResult();
|
| }
|
|
|
| - visitTryStatement(TryStatement node) {
|
| + ResolutionResult visitTryStatement(TryStatement node) {
|
| visit(node.tryBlock);
|
| if (node.catchBlocks.isEmpty && node.finallyBlock == null) {
|
| error(node.getEndToken().next, MessageKind.NO_CATCH_NOR_FINALLY);
|
| }
|
| visit(node.catchBlocks);
|
| visit(node.finallyBlock);
|
| + return const NoneResult();
|
| }
|
|
|
| - visitCatchBlock(CatchBlock node) {
|
| + ResolutionResult visitCatchBlock(CatchBlock node) {
|
| registry.registerCatchStatement();
|
| // Check that if catch part is present, then
|
| // it has one or two formal parameters.
|
| @@ -2637,10 +2923,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
|
| registry.registerInstantiatedClass(compiler.stackTraceClass);
|
| stackTraceElement.variables.type = compiler.stackTraceClass.rawType;
|
| }
|
| - }
|
| -
|
| - visitTypedef(Typedef node) {
|
| - internalError(node, 'typedef');
|
| + return const NoneResult();
|
| }
|
| }
|
|
|
|
|