Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(336)

Unified Diff: sdk/lib/_internal/compiler/implementation/typechecker.dart

Issue 15301003: Revert r22847: some dart2dart tests fail. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: sdk/lib/_internal/compiler/implementation/typechecker.dart
===================================================================
--- sdk/lib/_internal/compiler/implementation/typechecker.dart (revision 22847)
+++ sdk/lib/_internal/compiler/implementation/typechecker.dart (working copy)
@@ -18,22 +18,6 @@
}
/**
- * Class used to report different warnings for differrent kinds of members.
- */
-class MemberKind {
- static const MemberKind METHOD = const MemberKind("method");
- static const MemberKind OPERATOR = const MemberKind("operator");
- static const MemberKind PROPERTY = const MemberKind("property");
-
- final String name;
-
- const MemberKind(this.name);
-
- String toString() => name;
-}
-
-
-/**
* [ElementAccess] represents the access of [element], either as a property
* access or invocation.
*/
@@ -65,8 +49,6 @@
Element get element => member.element;
DartType computeType(Compiler compiler) => member.computeType(compiler);
-
- String toString() => 'MemberAccess($member)';
}
/// An access of an unresolved element.
@@ -78,8 +60,6 @@
DartType computeType(Compiler compiler) => compiler.types.dynamicType;
bool isCallable(Compiler compiler) => true;
-
- String toString() => 'DynamicAccess';
}
/**
@@ -93,19 +73,7 @@
assert(element != null);
}
- DartType computeType(Compiler compiler) {
- if (element.isGetter()) {
- FunctionType functionType = element.computeType(compiler);
- return functionType.returnType;
- } else if (element.isSetter()) {
- FunctionType functionType = element.computeType(compiler);
- return functionType.parameterTypes.head;
- } else {
- return element.computeType(compiler);
- }
- }
-
- String toString() => 'ResolvedAccess($element)';
+ DartType computeType(Compiler compiler) => element.computeType(compiler);
}
/**
@@ -121,25 +89,8 @@
Element get element => type.element;
DartType computeType(Compiler compiler) => type;
-
- String toString() => 'TypeAccess($type)';
}
-/**
- * An access of a type literal.
- */
-class TypeLiteralAccess extends ElementAccess {
- final Element element;
- TypeLiteralAccess(Element this.element) {
- assert(element != null);
- }
-
- DartType computeType(Compiler compiler) =>
- compiler.typeClass.computeType(compiler);
-
- String toString() => 'TypeLiteralAccess($element)';
-}
-
class TypeCheckerVisitor implements Visitor<DartType> {
final Compiler compiler;
final TreeElements elements;
@@ -147,7 +98,7 @@
Node lastSeenNode;
DartType expectedReturnType;
- final ClassElement currentClass;
+ ClassElement currentClass;
Link<DartType> cascadeTypes = const Link<DartType>();
@@ -158,10 +109,7 @@
DartType objectType;
DartType listType;
- TypeCheckerVisitor(this.compiler, TreeElements elements, this.types)
- : this.elements = elements,
- currentClass = elements.currentElement != null
- ? elements.currentElement.getEnclosingClass() : null {
+ TypeCheckerVisitor(this.compiler, this.elements, this.types) {
intType = compiler.intClass.computeType(compiler);
doubleType = compiler.doubleClass.computeType(compiler);
boolType = compiler.boolClass.computeType(compiler);
@@ -174,11 +122,6 @@
compiler.reportWarning(node, new TypeWarning(kind, arguments));
}
- reportTypeInfo(Spannable node, MessageKind kind, [Map arguments = const {}]) {
- compiler.reportDiagnostic(compiler.spanFromSpannable(node),
- 'Info: ${kind.message(arguments)}', api.Diagnostic.INFO);
- }
-
// TODO(karlklose): remove these functions.
DartType unhandledStatement() => StatementType.NOT_RETURNING;
DartType unhandledExpression() => types.dynamicType;
@@ -217,17 +160,15 @@
* Check if a value of type t can be assigned to a variable,
* parameter or return value of type s.
*/
- bool checkAssignable(Node node, DartType from, DartType to) {
- if (!types.isAssignable(from, to)) {
+ checkAssignable(Node node, DartType s, DartType t) {
+ if (!types.isAssignable(s, t)) {
reportTypeWarning(node, MessageKind.NOT_ASSIGNABLE,
- {'fromType': from, 'toType': to});
- return false;
+ {'fromType': s, 'toType': t});
}
- return true;
}
checkCondition(Expression condition) {
- checkAssignable(condition, analyze(condition), boolType);
+ checkAssignable(condition, boolType, analyze(condition));
}
void pushCascadeType(DartType type) {
@@ -319,6 +260,7 @@
}
DartType previous = expectedReturnType;
expectedReturnType = returnType;
+ if (element.isMember()) currentClass = element.getEnclosingClass();
StatementType bodyType = analyze(node.body);
if (returnType != types.voidType && returnType != types.dynamicType
&& bodyType != StatementType.RETURNING) {
@@ -355,8 +297,7 @@
return unhandledStatement();
}
- ElementAccess lookupMember(Node node, DartType type, SourceString name,
- MemberKind memberKind) {
+ ElementAccess lookupMethod(Node node, DartType type, SourceString name) {
if (identical(type, types.dynamicType)) {
return const DynamicAccess();
}
@@ -364,35 +305,17 @@
if (member != null) {
return new MemberAccess(member);
}
- switch (memberKind) {
- case MemberKind.METHOD:
- reportTypeWarning(node, MessageKind.METHOD_NOT_FOUND,
- {'className': type.name, 'memberName': name});
- break;
- case MemberKind.OPERATOR:
- reportTypeWarning(node, MessageKind.OPERATOR_NOT_FOUND,
- {'className': type.name, 'memberName': name});
- break;
- case MemberKind.PROPERTY:
- reportTypeWarning(node, MessageKind.PROPERTY_NOT_FOUND,
- {'className': type.name, 'memberName': name});
- break;
- }
+ reportTypeWarning(node, MessageKind.METHOD_NOT_FOUND,
+ {'className': type.name, 'memberName': name});
return const DynamicAccess();
}
- DartType lookupMemberType(Node node, DartType type, SourceString name,
- MemberKind memberKind) {
- return lookupMember(node, type, name, memberKind).computeType(compiler);
- }
-
- void analyzeArguments(Send send, Element element, DartType type,
- [LinkBuilder<DartType> argumentTypes]) {
+ // TODO(johnniwinther): Provide the element from which the type came in order
+ // to give better error messages.
+ void analyzeArguments(Send send, DartType type) {
Link<Node> arguments = send.arguments;
DartType unaliasedType = type.unalias(compiler);
if (identical(unaliasedType.kind, TypeKind.FUNCTION)) {
- assert(invariant(send, element != null, message: 'No element for $send'));
- bool error = false;
FunctionType funType = unaliasedType;
Link<DartType> parameterTypes = funType.parameterTypes;
Link<DartType> optionalParameterTypes = funType.optionalParameterTypes;
@@ -405,80 +328,57 @@
DartType namedParameterType =
funType.getNamedParameterType(argumentName);
if (namedParameterType == null) {
- error = true;
// TODO(johnniwinther): Provide better information on the called
// function.
reportTypeWarning(argument, MessageKind.NAMED_ARGUMENT_NOT_FOUND,
{'argumentName': argumentName});
- DartType argumentType = analyze(argument);
- if (argumentTypes != null) argumentTypes.addLast(argumentType);
+ analyze(argument);
} else {
- DartType argumentType = analyze(argument);
- if (argumentTypes != null) argumentTypes.addLast(argumentType);
- if (!checkAssignable(argument, argumentType, namedParameterType)) {
- error = true;
- }
+ checkAssignable(argument, namedParameterType, analyze(argument));
}
} else {
if (parameterTypes.isEmpty) {
if (optionalParameterTypes.isEmpty) {
- error = true;
// TODO(johnniwinther): Provide better information on the
// called function.
reportTypeWarning(argument, MessageKind.ADDITIONAL_ARGUMENT);
- DartType argumentType = analyze(argument);
- if (argumentTypes != null) argumentTypes.addLast(argumentType);
+ analyze(argument);
} else {
- DartType argumentType = analyze(argument);
- if (argumentTypes != null) argumentTypes.addLast(argumentType);
- if (!checkAssignable(argument,
- argumentType, optionalParameterTypes.head)) {
- error = true;
- }
+ checkAssignable(argument, optionalParameterTypes.head,
+ analyze(argument));
optionalParameterTypes = optionalParameterTypes.tail;
}
} else {
- DartType argumentType = analyze(argument);
- if (argumentTypes != null) argumentTypes.addLast(argumentType);
- if (!checkAssignable(argument, argumentType, parameterTypes.head)) {
- error = true;
- }
+ checkAssignable(argument, parameterTypes.head, analyze(argument));
parameterTypes = parameterTypes.tail;
}
}
arguments = arguments.tail;
}
if (!parameterTypes.isEmpty) {
- error = true;
// TODO(johnniwinther): Provide better information on the called
// function.
reportTypeWarning(send, MessageKind.MISSING_ARGUMENT,
{'argumentType': parameterTypes.head});
}
- if (error) {
- reportTypeInfo(element, MessageKind.THIS_IS_THE_METHOD);
- }
} else {
while(!arguments.isEmpty) {
- DartType argumentType = analyze(arguments.head);
- if (argumentTypes != null) argumentTypes.addLast(argumentType);
+ analyze(arguments.head);
arguments = arguments.tail;
}
}
}
- DartType analyzeInvocation(Send node, ElementAccess elementAccess,
- [LinkBuilder<DartType> argumentTypes]) {
+ DartType analyzeInvocation(Send node, ElementAccess elementAccess) {
DartType type = elementAccess.computeType(compiler);
if (elementAccess.isCallable(compiler)) {
- analyzeArguments(node, elementAccess.element, type, argumentTypes);
+ analyzeArguments(node, type);
} else {
reportTypeWarning(node, MessageKind.NOT_CALLABLE,
{'elementName': elementAccess.element.name});
- analyzeArguments(node, elementAccess.element, types.dynamicType,
- argumentTypes);
+ analyzeArguments(node, types.dynamicType);
}
if (identical(type.kind, TypeKind.FUNCTION)) {
FunctionType funType = type;
@@ -488,104 +388,6 @@
}
}
- /**
- * Computes the [ElementAccess] for [name] on the [node] possibly using the
- * [element] provided for [node] by the resolver.
- */
- ElementAccess computeAccess(Send node, SourceString name, Element element,
- MemberKind memberKind) {
- if (node.receiver != null) {
- Element receiverElement = elements[node.receiver];
- if (receiverElement != null) {
- if (receiverElement.isPrefix()) {
- assert(invariant(node, element != null,
- message: 'Prefixed node has no element.'));
- return computeResolvedAccess(node, name, element, memberKind);
- }
- }
- // e.foo() for some expression e.
- DartType receiverType = analyze(node.receiver);
- if (receiverType.isDynamic ||
- receiverType.isMalformed ||
- receiverType.isVoid) {
- return const DynamicAccess();
- }
- TypeKind receiverKind = receiverType.kind;
- if (identical(receiverKind, TypeKind.TYPEDEF)) {
- // TODO(johnniwinther): handle typedefs.
- return const DynamicAccess();
- }
- if (identical(receiverKind, TypeKind.FUNCTION)) {
- // TODO(johnniwinther): handle functions.
- return const DynamicAccess();
- }
- if (identical(receiverKind, TypeKind.TYPE_VARIABLE)) {
- // TODO(johnniwinther): handle type variables.
- return const DynamicAccess();
- }
- assert(invariant(node.receiver,
- identical(receiverKind, TypeKind.INTERFACE),
- message: "interface type expected, got ${receiverKind}"));
- return lookupMember(node, receiverType, name, memberKind);
- } else {
- return computeResolvedAccess(node, name, element, memberKind);
- }
- }
-
- /**
- * Computes the [ElementAccess] for [name] on the [node] using the [element]
- * provided for [node] by the resolver.
- */
- ElementAccess computeResolvedAccess(Send node, SourceString name,
- Element element, MemberKind memberKind) {
- if (Elements.isUnresolved(element)) {
- // foo() where foo is unresolved.
- return const DynamicAccess();
- } else if (element.isMember()) {
- // foo() where foo is an instance member.
- return lookupMember(node, currentClass.computeType(compiler),
- name, memberKind);
- } else if (element.isFunction()) {
- // foo() where foo is a method in the same class.
- return new ResolvedAccess(element);
- } else if (element.isVariable() ||
- element.isParameter() ||
- element.isField()) {
- // foo() where foo is a field in the same class.
- return new ResolvedAccess(element);
- } else if (element.impliesType()) {
- // The literal `Foo` where Foo is a class, a typedef, or a type variable.
- if (elements.getType(node) != null) {
- assert(invariant(node, identical(compiler.typeClass,
- elements.getType(node).element),
- message: 'Expected type literal type: '
- '${elements.getType(node)}'));
- return new TypeLiteralAccess(element);
- }
- return new ResolvedAccess(element);
- } else if (element.isGetter() || element.isSetter()) {
- return new ResolvedAccess(element);
- } else {
- compiler.internalErrorOnElement(
- element, 'unexpected element kind ${element.kind}');
- }
- }
-
- /**
- * Computes the type of the access of [name] on the [node] possibly using the
- * [element] provided for [node] by the resolver.
- */
- DartType computeAccessType(Send node, SourceString name, Element element,
- MemberKind memberKind) {
- DartType type =
- computeAccess(node, name, element, memberKind).computeType(compiler);
- if (type == null) {
- compiler.internalError('type is null on access of $name on $node',
- node: node);
- }
- return type;
- }
-
DartType visitSend(Send node) {
Element element = elements[node];
@@ -606,252 +408,117 @@
if (node.isOperator && identical(name, 'is')) {
analyze(node.receiver);
return boolType;
- } if (node.isOperator && identical(name, 'as')) {
- analyze(node.receiver);
- return elements.getType(node.arguments.head);
} else if (node.isOperator) {
- final Node receiver = node.receiver;
- final DartType receiverType = analyze(receiver);
- if (identical(name, '==') || identical(name, '!=')
- // TODO(johnniwinther): Remove these.
- || identical(name, '===') || identical(name, '!==')) {
- // Analyze argument.
- analyze(node.arguments.head);
+ final Node firstArgument = node.receiver;
+ final DartType firstArgumentType = analyze(node.receiver);
+ final arguments = node.arguments;
+ final Node secondArgument = arguments.isEmpty ? null : arguments.head;
+ final DartType secondArgumentType =
+ analyzeWithDefault(secondArgument, null);
+
+ if (identical(name, '+') || identical(name, '=') ||
+ identical(name, '-') || identical(name, '*') ||
+ identical(name, '/') || identical(name, '%') ||
+ identical(name, '~/') || identical(name, '|') ||
+ identical(name, '&') || identical(name, '^') ||
+ identical(name, '~')|| identical(name, '<<') ||
+ identical(name, '>>') || identical(name, '[]')) {
+ return types.dynamicType;
+ } else if (identical(name, '<') || identical(name, '>') ||
+ identical(name, '<=') || identical(name, '>=') ||
+ identical(name, '==') || identical(name, '!=') ||
+ identical(name, '===') || identical(name, '!==')) {
return boolType;
} else if (identical(name, '||') ||
- identical(name, '&&')) {
- checkAssignable(receiver, receiverType, boolType);
- final Node argument = node.arguments.head;
- final DartType argumentType = analyze(argument);
- checkAssignable(argument, argumentType, boolType);
+ identical(name, '&&') ||
+ identical(name, '!')) {
+ checkAssignable(firstArgument, boolType, firstArgumentType);
+ if (!arguments.isEmpty) {
+ // TODO(karlklose): check number of arguments in validator.
+ checkAssignable(secondArgument, boolType, secondArgumentType);
+ }
return boolType;
- } else if (identical(name, '!')) {
- checkAssignable(receiver, receiverType, boolType);
- return boolType;
- } else if (identical(name, '?')) {
- return boolType;
+ } else {
+ return unhandledExpression();
}
- SourceString operatorName = selector.source;
- if (identical(name, '-') && node.arguments.isEmpty) {
- operatorName = const SourceString('unary-');
- }
- assert(invariant(node,
- identical(name, '+') || identical(name, '=') ||
- identical(name, '-') || identical(name, '*') ||
- identical(name, '/') || identical(name, '%') ||
- identical(name, '~/') || identical(name, '|') ||
- identical(name, '&') || identical(name, '^') ||
- identical(name, '~')|| identical(name, '<<') ||
- identical(name, '>>') ||
- identical(name, '<') || identical(name, '>') ||
- identical(name, '<=') || identical(name, '>=') ||
- identical(name, '[]'),
- message: 'Unexpected operator $name'));
- ElementAccess access = lookupMember(node, receiverType,
- operatorName, MemberKind.OPERATOR);
- LinkBuilder<DartType> argumentTypesBuilder = new LinkBuilder<DartType>();
- DartType resultType =
- analyzeInvocation(node, access, argumentTypesBuilder);
- if (identical(receiverType.element, compiler.intClass)) {
- if (identical(name, '+') ||
- identical(operatorName, const SourceString('-')) ||
- identical(name, '*') ||
- identical(name, '%')) {
- DartType argumentType = argumentTypesBuilder.toLink().head;
- if (identical(argumentType.element, compiler.intClass)) {
- return intType;
- } else if (identical(argumentType.element, compiler.doubleClass)) {
- return doubleType;
- }
- }
- }
- return resultType;
} else if (node.isPropertyAccess) {
- ElementAccess access =
- computeAccess(node, selector.source, element, MemberKind.PROPERTY);
- return access.computeType(compiler);
+ if (node.receiver != null) {
+ // TODO(karlklose): we cannot handle fields.
+ return unhandledExpression();
+ }
+ if (element == null) return types.dynamicType;
+ return computeType(element);
+
} else if (node.isFunctionObjectInvocation) {
return unhandledExpression();
} else {
- ElementAccess access =
- computeAccess(node, selector.source, element, MemberKind.METHOD);
- return analyzeInvocation(node, access);
- }
- }
-
- /**
- * Checks [: target o= value :] for some operator o, and returns the type
- * of the result. This method also handles increment/decrement expressions
- * like [: target++ :].
- */
- DartType checkAssignmentOperator(SendSet node,
- SourceString operatorName,
- Node valueNode,
- DartType value) {
- assert(invariant(node, !node.isIndex));
- Element element = elements[node];
- Identifier selector = node.selector;
- DartType target =
- computeAccessType(node, selector.source, element, MemberKind.PROPERTY);
- // [operator] is the type of operator+ or operator- on [target].
- DartType operator =
- lookupMemberType(node, target, operatorName, MemberKind.OPERATOR);
- if (operator is FunctionType) {
- FunctionType operatorType = operator;
- // [result] is the type of target o value.
- DartType result = operatorType.returnType;
- DartType operatorArgument = operatorType.parameterTypes.head;
- // Check target o value.
- bool validValue = checkAssignable(valueNode, value, operatorArgument);
- if (validValue || !(node.isPrefix || node.isPostfix)) {
- // Check target = result.
- checkAssignable(node.assignmentOperator, result, target);
- }
- return node.isPostfix ? target : result;
- }
- return types.dynamicType;
- }
-
- /**
- * Checks [: base[key] o= value :] for some operator o, and returns the type
- * of the result. This method also handles increment/decrement expressions
- * like [: base[key]++ :].
- */
- DartType checkIndexAssignmentOperator(SendSet node,
- SourceString operatorName,
- Node valueNode,
- DartType value) {
- assert(invariant(node, node.isIndex));
- final DartType base = analyze(node.receiver);
- final Node keyNode = node.arguments.head;
- final DartType key = analyze(keyNode);
-
- // [indexGet] is the type of operator[] on [base].
- DartType indexGet = lookupMemberType(
- node, base, const SourceString('[]'), MemberKind.OPERATOR);
- if (indexGet is FunctionType) {
- FunctionType indexGetType = indexGet;
- DartType indexGetKey = indexGetType.parameterTypes.head;
- // Check base[key].
- bool validKey = checkAssignable(keyNode, key, indexGetKey);
-
- // [element] is the type of base[key].
- DartType element = indexGetType.returnType;
- // [operator] is the type of operator o on [element].
- DartType operator = lookupMemberType(
- node, element, operatorName, MemberKind.OPERATOR);
- if (operator is FunctionType) {
- FunctionType operatorType = operator;
-
- // Check base[key] o value.
- DartType operatorArgument = operatorType.parameterTypes.head;
- bool validValue = checkAssignable(valueNode, value, operatorArgument);
-
- // [result] is the type of base[key] o value.
- DartType result = operatorType.returnType;
-
- // [indexSet] is the type of operator[]= on [base].
- DartType indexSet = lookupMemberType(
- node, base, const SourceString('[]='), MemberKind.OPERATOR);
- if (indexSet is FunctionType) {
- FunctionType indexSetType = indexSet;
- DartType indexSetKey = indexSetType.parameterTypes.head;
- DartType indexSetValue =
- indexSetType.parameterTypes.tail.head;
-
- if (validKey || indexGetKey != indexSetKey) {
- // Only check base[key] on []= if base[key] was valid for [] or
- // if the key types differ.
- checkAssignable(keyNode, key, indexSetKey);
+ ElementAccess computeMethod() {
+ if (node.receiver != null) {
+ // e.foo() for some expression e.
+ DartType receiverType = analyze(node.receiver);
+ if (receiverType.element == compiler.dynamicClass ||
+ receiverType == null ||
+ receiverType.isMalformed ||
+ receiverType.isVoid) {
+ return const DynamicAccess();
}
- // Check base[key] = result
- if (validValue || !(node.isPrefix || node.isPostfix)) {
- checkAssignable(node.assignmentOperator, result, indexSetValue);
+ TypeKind receiverKind = receiverType.kind;
+ if (identical(receiverKind, TypeKind.TYPEDEF)) {
+ // TODO(karlklose): handle typedefs.
+ return const DynamicAccess();
}
+ if (identical(receiverKind, TypeKind.TYPE_VARIABLE)) {
+ // TODO(karlklose): handle type variables.
+ return const DynamicAccess();
+ }
+ if (identical(receiverKind, TypeKind.FUNCTION)) {
+ // TODO(karlklose): handle getters.
+ return const DynamicAccess();
+ }
+ assert(invariant(node.receiver,
+ identical(receiverKind, TypeKind.INTERFACE),
+ message: "interface type expected, got ${receiverKind}"));
+ return lookupMethod(selector, receiverType, selector.source);
+ } else {
+ if (Elements.isUnresolved(element)) {
+ // foo() where foo is unresolved.
+ return const DynamicAccess();
+ } else if (element.isFunction()) {
+ // foo() where foo is a method in the same class.
+ return new ResolvedAccess(element);
+ } else if (element.isVariable() || element.isField()) {
+ // foo() where foo is a field in the same class.
+ return new ResolvedAccess(element);
+ } else if (element.isGetter()) {
+ // TODO(karlklose): handle getters.
+ return const DynamicAccess();
+ } else if (element.isClass()) {
+ // TODO(karlklose): handle type literals.
+ return const DynamicAccess();
+ } else {
+ compiler.internalErrorOnElement(
+ element, 'unexpected element kind ${element.kind}');
+ }
}
- return node.isPostfix ? element : result;
}
+ return analyzeInvocation(node, computeMethod());
}
- return types.dynamicType;
}
visitSendSet(SendSet node) {
- Element element = elements[node];
Identifier selector = node.selector;
final name = node.assignmentOperator.source.stringValue;
- if (identical(name, '=')) {
- // e1 = value
- if (node.isIndex) {
- // base[key] = value
- final DartType base = analyze(node.receiver);
- final Node keyNode = node.arguments.head;
- final DartType key = analyze(keyNode);
- final Node valueNode = node.arguments.tail.head;
- final DartType value = analyze(valueNode);
- DartType indexSet = lookupMemberType(
- node, base, const SourceString('[]='), MemberKind.OPERATOR);
- if (indexSet is FunctionType) {
- FunctionType indexSetType = indexSet;
- DartType indexSetKey = indexSetType.parameterTypes.head;
- checkAssignable(keyNode, key, indexSetKey);
- DartType indexSetValue = indexSetType.parameterTypes.tail.head;
- checkAssignable(node.assignmentOperator, value, indexSetValue);
- }
- return value;
- } else {
- // target = value
- DartType target = computeAccessType(node, selector.source,
- element, MemberKind.PROPERTY);
- final Node valueNode = node.arguments.head;
- final DartType value = analyze(valueNode);
- checkAssignable(node.assignmentOperator, value, target);
- return value;
- }
- } else if (identical(name, '++') || identical(name, '--')) {
- // e++ or e--
- SourceString operatorName = identical(name, '++')
- ? const SourceString('+') : const SourceString('-');
- if (node.isIndex) {
- // base[key]++, base[key]--, ++base[key], or --base[key]
- return checkIndexAssignmentOperator(
- node, operatorName, node.assignmentOperator, intType);
- } else {
- // target++, target--, ++target, or --target
- return checkAssignmentOperator(
- node, operatorName, node.assignmentOperator, intType);
- }
+ if (identical(name, '++') || identical(name, '--')) {
+ final Element element = elements[node.selector];
+ final DartType receiverType = computeType(element);
+ // TODO(karlklose): this should be the return type instead of int.
+ return node.isPrefix ? intType : receiverType;
} else {
- // e1 o= e2 for some operator o.
- SourceString operatorName;
- switch (name) {
- case '+=': operatorName = const SourceString('+'); break;
- case '-=': operatorName = const SourceString('-'); break;
- case '*=': operatorName = const SourceString('*'); break;
- case '/=': operatorName = const SourceString('/'); break;
- case '%=': operatorName = const SourceString('%'); break;
- case '~/=': operatorName = const SourceString('~/'); break;
- case '&=': operatorName = const SourceString('&'); break;
- case '|=': operatorName = const SourceString('|'); break;
- case '^=': operatorName = const SourceString('^'); break;
- case '<<=': operatorName = const SourceString('<<'); break;
- case '>>=': operatorName = const SourceString('>>'); break;
- default:
- compiler.internalError(
- 'Unexpected assignment operator $name', node: node);
- }
- if (node.isIndex) {
- // base[key] o= value for some operator o.
- final Node valueNode = node.arguments.tail.head;
- final DartType value = analyze(valueNode);
- return checkIndexAssignmentOperator(
- node, operatorName, valueNode, value);
- } else {
- // target o= value for some operator o.
- final Node valueNode = node.arguments.head;
- final DartType value = analyze(valueNode);
- return checkAssignmentOperator(node, operatorName, valueNode, value);
- }
+ DartType targetType = computeType(elements[node]);
+ Node value = node.arguments.head;
+ checkAssignable(value, targetType, analyze(value));
+ return targetType;
}
}
@@ -883,30 +550,11 @@
DartType visitNewExpression(NewExpression node) {
Element element = elements[node.send];
- DartType constructorType = computeType(element);
- DartType newType = elements.getType(node);
- // TODO(johnniwinther): Use [:lookupMember:] to account for type variable
- // substitution of parameter types.
- if (identical(newType.kind, TypeKind.INTERFACE)) {
- InterfaceType newInterfaceType = newType;
- constructorType = constructorType.subst(
- newInterfaceType.typeArguments,
- newInterfaceType.element.typeVariables);
- }
- analyzeArguments(node.send, element, constructorType);
- return newType;
+ analyzeArguments(node.send, computeType(element));
+ return analyze(node.send.selector);
}
DartType visitLiteralList(LiteralList node) {
- InterfaceType listType = elements.getType(node);
- DartType listElementType = listType.typeArguments.head;
- for (Link<Node> link = node.elements.nodes;
- !link.isEmpty;
- link = link.tail) {
- Node element = link.head;
- DartType elementType = analyze(element);
- checkAssignable(element, elementType, listElementType);
- }
return listType;
}
@@ -962,7 +610,7 @@
&& !types.isAssignable(expressionType, types.voidType)) {
reportTypeWarning(expression, MessageKind.RETURN_VALUE_IN_VOID);
} else {
- checkAssignable(expression, expressionType, expectedReturnType);
+ checkAssignable(expression, expectedReturnType, expressionType);
}
// Let f be the function immediately enclosing a return statement of the
@@ -982,7 +630,6 @@
return types.dynamicType;
}
- // TODO(johnniwinther): Remove this.
DartType computeType(Element element) {
if (Elements.isUnresolved(element)) return types.dynamicType;
DartType result = element.computeType(compiler);
@@ -1005,12 +652,12 @@
}
for (Link<Node> link = node.definitions.nodes; !link.isEmpty;
link = link.tail) {
- Node definition = link.head;
- compiler.ensure(definition is Identifier || definition is SendSet);
- if (definition is Send) {
- SendSet initialization = definition;
- DartType initializer = analyzeNonVoid(initialization.arguments.head);
- checkAssignable(initialization.assignmentOperator, initializer, type);
+ Node initialization = link.head;
+ compiler.ensure(initialization is Identifier
+ || initialization is Send);
+ if (initialization is Send) {
+ DartType initializer = analyzeNonVoid(link.head);
+ checkAssignable(node, type, initializer);
}
}
return StatementType.NOT_RETURNING;
@@ -1086,19 +733,7 @@
}
visitLiteralMap(LiteralMap node) {
- InterfaceType mapType = elements.getType(node);
- DartType mapKeyType = mapType.typeArguments.head;
- DartType mapValueType = mapType.typeArguments.tail.head;
- for (Link<Node> link = node.entries.nodes;
- !link.isEmpty;
- link = link.tail) {
- LiteralMapEntry entry = link.head;
- DartType keyType = analyze(entry.key);
- checkAssignable(entry.key, keyType, mapKeyType);
- DartType valueType = analyze(entry.value);
- checkAssignable(entry.value, valueType, mapValueType);
- }
- return mapType;
+ return unhandledExpression();
}
visitLiteralMapEntry(LiteralMapEntry node) {

Powered by Google App Engine
This is Rietveld 408576698