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

Unified Diff: sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart

Issue 11348067: Fix operator handling. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Apply style remarks to the rest the file. Created 8 years, 1 month 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/types/concrete_types_inferrer.dart
diff --git a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
index e619ae512afe706aaac9c72f6508db023b6599d5..d5b46c68cb9fe26ab093c9b12d9a5d4109fc9a4f 100644
--- a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
@@ -94,6 +94,7 @@ abstract class ConcreteType {
ConcreteType union(ConcreteType other);
bool isUnkown();
+ bool isEmpty();
Set<BaseType> get baseTypes;
/**
@@ -109,6 +110,7 @@ abstract class ConcreteType {
class UnknownConcreteType implements ConcreteType {
const UnknownConcreteType();
bool isUnkown() => true;
+ bool isEmpty() => false;
bool operator ==(ConcreteType other) => identical(this, other);
Set<BaseType> get baseTypes =>
new Set<BaseType>.from([const UnknownBaseType()]);
@@ -131,6 +133,7 @@ class UnionType implements ConcreteType {
UnionType(this.baseTypes);
bool isUnkown() => false;
+ bool isEmpty() => baseTypes.isEmpty;
bool operator ==(ConcreteType other) {
if (other is! UnionType) return false;
@@ -1047,31 +1050,54 @@ class TypeInferrerVisitor extends ResolvedVisitor<ConcreteType> {
return argumentType;
}
- SourceString canonicalizeCompoundOperator(String op) {
+ SourceString canonicalizeCompoundOperator(SourceString op) {
// TODO(ahe): This class should work on elements or selectors, not
// names. Otherwise, it is repeating work the resolver has
// already done (or should have done). In this case, the problem
// is that the resolver is not recording the selectors it is
// registering in registerBinaryOperator in
// ResolverVisitor.visitSendSet.
- if (op == '++') return const SourceString(r'+');
- else return const SourceString(r'-');
+ String stringValue = op.stringValue;
+ if (stringValue == '++') return const SourceString(r'+');
+ else if (stringValue == '--') return const SourceString(r'-');
+ else return Elements.mapToUserOperatorOrNull(op);
}
// TODO(polux): handle sendset as expression
ConcreteType visitSendSet(SendSet node) {
- Identifier selector = node.selector;
- final name = node.assignmentOperator.source.stringValue;
+ // Operator []= has a different behaviour than other send sets: it is
+ // actually a send whose return type is that of its second argument.
+ if (node.selector.asIdentifier().source.stringValue == '[]') {
+ ConcreteType receiverType = analyze(node.receiver);
+ ArgumentsTypes argumentsTypes = analyzeArguments(node.arguments);
+ analyzeDynamicSend(receiverType, const SourceString('[]='),
+ argumentsTypes);
+ return argumentsTypes.positional[1];
+ }
+
+ // All other operators have a single argument (++ and -- have an implicit
+ // argument: 1). We will store its type in argumentType.
ConcreteType argumentType;
- if (name == '++' || name == '--') {
+ SourceString operatorName = node.assignmentOperator.source;
+ SourceString compoundOperatorName =
+ canonicalizeCompoundOperator(node.assignmentOperator.source);
+ // ++, --, +=, -=, ...
+ if (compoundOperatorName != null) {
ConcreteType receiverType = visitGetterSend(node);
- SourceString canonicalizedMethodName = canonicalizeCompoundOperator(name);
- List<ConcreteType> positionalArguments = <ConcreteType>[
- new ConcreteType.singleton(inferrer.baseTypes.intBaseType)];
- ArgumentsTypes argumentsTypes =
- new ArgumentsTypes(positionalArguments, new Map());
- argumentType = analyzeDynamicSend(receiverType, canonicalizedMethodName,
+ // argumentsTypes is either computed from the actual arguments or [{int}]
+ // in case of ++ or --.
+ ArgumentsTypes argumentsTypes;
+ if (operatorName.stringValue == '++'
+ || operatorName.stringValue == '--') {
+ List<ConcreteType> positionalArguments = <ConcreteType>[
+ new ConcreteType.singleton(inferrer.baseTypes.intBaseType)];
+ argumentsTypes = new ArgumentsTypes(positionalArguments, new Map());
+ } else {
+ argumentsTypes = analyzeArguments(node.arguments);
+ }
+ argumentType = analyzeDynamicSend(receiverType, compoundOperatorName,
argumentsTypes);
+ // The simple assignment case: receiver = argument.
} else {
argumentType = analyze(node.argumentsNode);
}
@@ -1359,47 +1385,6 @@ class TypeInferrerVisitor extends ResolvedVisitor<ConcreteType> {
inferrer.fail(node, 'not implemented');
}
- // TODO(polux): handle unary operators and share this list with the rest of
- // dart2js.
- final Set<SourceString> operators = new Set<SourceString>()
- ..add(const SourceString('=='))
- ..add(const SourceString('!='))
- ..add(const SourceString('~'))
- ..add(const SourceString('[]'))
- ..add(const SourceString('[]='))
- ..add(const SourceString('*'))
- ..add(const SourceString('*='))
- ..add(const SourceString('/'))
- ..add(const SourceString('/='))
- ..add(const SourceString('%'))
- ..add(const SourceString('%='))
- ..add(const SourceString('~/'))
- ..add(const SourceString('~/='))
- ..add(const SourceString('+'))
- ..add(const SourceString('+='))
- ..add(const SourceString('-'))
- ..add(const SourceString('-='))
- ..add(const SourceString('<<'))
- ..add(const SourceString('<<='))
- ..add(const SourceString('>>'))
- ..add(const SourceString('>>='))
- ..add(const SourceString('>='))
- ..add(const SourceString('>'))
- ..add(const SourceString('<='))
- ..add(const SourceString('<'))
- ..add(const SourceString('&'))
- ..add(const SourceString('&='))
- ..add(const SourceString('^'))
- ..add(const SourceString('^='))
- ..add(const SourceString('|'))
- ..add(const SourceString('|='));
-
- SourceString canonicalizeMethodName(SourceString s) {
- return operators.contains(s)
- ? Elements.constructOperatorName(s, false)
- : s;
- }
-
ConcreteType analyzeDynamicSend(ConcreteType receiverType,
SourceString canonicalizedMethodName,
ArgumentsTypes argumentsTypes) {
@@ -1437,6 +1422,14 @@ class TypeInferrerVisitor extends ResolvedVisitor<ConcreteType> {
return result;
}
+ SourceString canonicalizeMethodName(SourceString name) {
+ // TODO(polux): handle unary-
+ SourceString operatorName =
+ Elements.constructOperatorNameOrNull(name, false);
+ if (operatorName != null) return operatorName;
+ return name;
+ }
+
ConcreteType visitDynamicSend(Send node) {
ConcreteType receiverType = (node.receiver != null)
? analyze(node.receiver)
@@ -1445,7 +1438,16 @@ class TypeInferrerVisitor extends ResolvedVisitor<ConcreteType> {
SourceString name =
canonicalizeMethodName(node.selector.asIdentifier().source);
ArgumentsTypes argumentsTypes = analyzeArguments(node.arguments);
- return analyzeDynamicSend(receiverType, name, argumentsTypes);
+ if (name.stringValue == '!=') {
+ ConcreteType returnType = analyzeDynamicSend(receiverType,
+ const SourceString('=='),
+ argumentsTypes);
+ return returnType.isEmpty()
+ ? returnType
+ : new ConcreteType.singleton(inferrer.baseTypes.boolBaseType);
+ } else {
+ return analyzeDynamicSend(receiverType, name, argumentsTypes);
+ }
}
ConcreteType visitForeignSend(Send node) {
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/elements/elements.dart ('k') | tests/compiler/dart2js/cpa_inference_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698