| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library inferrer_visitor; | 5 library inferrer_visitor; |
| 6 | 6 |
| 7 import 'dart:collection' show IterableMixin; | 7 import 'dart:collection' show IterableMixin; |
| 8 | 8 |
| 9 import '../common.dart'; | 9 import '../common.dart'; |
| 10 import '../options.dart' show CompilerOptions; |
| 10 import '../compiler.dart' show Compiler; | 11 import '../compiler.dart' show Compiler; |
| 11 import '../constants/constant_system.dart'; | 12 import '../constants/constant_system.dart'; |
| 12 import '../constants/expressions.dart'; | 13 import '../constants/expressions.dart'; |
| 13 import '../dart_types.dart'; | 14 import '../dart_types.dart'; |
| 14 import '../elements/elements.dart'; | 15 import '../elements/elements.dart'; |
| 15 import '../resolution/operators.dart'; | 16 import '../resolution/operators.dart'; |
| 16 import '../resolution/semantic_visitor.dart'; | 17 import '../resolution/semantic_visitor.dart'; |
| 17 import '../resolution/tree_elements.dart' show TreeElements; | 18 import '../resolution/tree_elements.dart' show TreeElements; |
| 18 import '../tree/tree.dart'; | 19 import '../tree/tree.dart'; |
| 19 import '../types/constants.dart' show computeTypeMask; | 20 import '../types/constants.dart' show computeTypeMask; |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 364 | 365 |
| 365 /** | 366 /** |
| 366 * Records that the captured variable [local] is read. | 367 * Records that the captured variable [local] is read. |
| 367 */ | 368 */ |
| 368 void recordCapturedLocalRead(Local local); | 369 void recordCapturedLocalRead(Local local); |
| 369 | 370 |
| 370 /** | 371 /** |
| 371 * Records that the variable [local] is being updated. | 372 * Records that the variable [local] is being updated. |
| 372 */ | 373 */ |
| 373 void recordLocalUpdate(Local local, T type); | 374 void recordLocalUpdate(Local local, T type); |
| 375 |
| 376 /// The [ClosedWorld] on which inference reasoning is based. |
| 377 ClosedWorld get closedWorld; |
| 374 } | 378 } |
| 375 | 379 |
| 376 /** | 380 /** |
| 377 * Placeholder for inferred types of local variables. | 381 * Placeholder for inferred types of local variables. |
| 378 */ | 382 */ |
| 379 class LocalsHandler<T> { | 383 class LocalsHandler<T> { |
| 380 final Compiler compiler; | 384 final CompilerOptions options; |
| 381 final TypeSystem<T> types; | 385 final TypeSystem<T> types; |
| 382 final MinimalInferrerEngine<T> inferrer; | 386 final MinimalInferrerEngine<T> inferrer; |
| 383 final VariableScope<T> locals; | 387 final VariableScope<T> locals; |
| 384 final Map<Local, Element> captured; | 388 final Map<Local, Element> captured; |
| 385 final Map<Local, Element> capturedAndBoxed; | 389 final Map<Local, Element> capturedAndBoxed; |
| 386 final FieldInitializationScope<T> fieldScope; | 390 final FieldInitializationScope<T> fieldScope; |
| 387 LocalsHandler<T> tryBlock; | 391 LocalsHandler<T> tryBlock; |
| 388 bool seenReturnOrThrow = false; | 392 bool seenReturnOrThrow = false; |
| 389 bool seenBreakOrContinue = false; | 393 bool seenBreakOrContinue = false; |
| 390 | 394 |
| 391 bool get aborts { | 395 bool get aborts { |
| 392 return seenReturnOrThrow || seenBreakOrContinue; | 396 return seenReturnOrThrow || seenBreakOrContinue; |
| 393 } | 397 } |
| 394 | 398 |
| 395 bool get inTryBlock => tryBlock != null; | 399 bool get inTryBlock => tryBlock != null; |
| 396 | 400 |
| 397 LocalsHandler(this.inferrer, this.types, this.compiler, Node block, | 401 LocalsHandler(this.inferrer, this.types, this.options, Node block, |
| 398 [this.fieldScope]) | 402 [this.fieldScope]) |
| 399 : locals = new VariableScope<T>(block), | 403 : locals = new VariableScope<T>(block), |
| 400 captured = new Map<Local, Element>(), | 404 captured = new Map<Local, Element>(), |
| 401 capturedAndBoxed = new Map<Local, Element>(), | 405 capturedAndBoxed = new Map<Local, Element>(), |
| 402 tryBlock = null; | 406 tryBlock = null; |
| 403 | 407 |
| 404 LocalsHandler.from(LocalsHandler<T> other, Node block, | 408 LocalsHandler.from(LocalsHandler<T> other, Node block, |
| 405 {bool useOtherTryBlock: true}) | 409 {bool useOtherTryBlock: true}) |
| 406 : locals = new VariableScope<T>(block, other.locals), | 410 : locals = new VariableScope<T>(block, other.locals), |
| 407 fieldScope = new FieldInitializationScope<T>.from(other.fieldScope), | 411 fieldScope = new FieldInitializationScope<T>.from(other.fieldScope), |
| 408 captured = other.captured, | 412 captured = other.captured, |
| 409 capturedAndBoxed = other.capturedAndBoxed, | 413 capturedAndBoxed = other.capturedAndBoxed, |
| 410 types = other.types, | 414 types = other.types, |
| 411 inferrer = other.inferrer, | 415 inferrer = other.inferrer, |
| 412 compiler = other.compiler { | 416 options = other.options { |
| 413 tryBlock = useOtherTryBlock ? other.tryBlock : this; | 417 tryBlock = useOtherTryBlock ? other.tryBlock : this; |
| 414 } | 418 } |
| 415 | 419 |
| 416 LocalsHandler.deepCopyOf(LocalsHandler<T> other) | 420 LocalsHandler.deepCopyOf(LocalsHandler<T> other) |
| 417 : locals = new VariableScope<T>.deepCopyOf(other.locals), | 421 : locals = new VariableScope<T>.deepCopyOf(other.locals), |
| 418 fieldScope = new FieldInitializationScope<T>.from(other.fieldScope), | 422 fieldScope = new FieldInitializationScope<T>.from(other.fieldScope), |
| 419 captured = other.captured, | 423 captured = other.captured, |
| 420 capturedAndBoxed = other.capturedAndBoxed, | 424 capturedAndBoxed = other.capturedAndBoxed, |
| 421 tryBlock = other.tryBlock, | 425 tryBlock = other.tryBlock, |
| 422 types = other.types, | 426 types = other.types, |
| 423 inferrer = other.inferrer, | 427 inferrer = other.inferrer, |
| 424 compiler = other.compiler; | 428 options = other.options; |
| 425 | 429 |
| 426 LocalsHandler.topLevelCopyOf(LocalsHandler<T> other) | 430 LocalsHandler.topLevelCopyOf(LocalsHandler<T> other) |
| 427 : locals = new VariableScope<T>.topLevelCopyOf(other.locals), | 431 : locals = new VariableScope<T>.topLevelCopyOf(other.locals), |
| 428 fieldScope = new FieldInitializationScope<T>.from(other.fieldScope), | 432 fieldScope = new FieldInitializationScope<T>.from(other.fieldScope), |
| 429 captured = other.captured, | 433 captured = other.captured, |
| 430 capturedAndBoxed = other.capturedAndBoxed, | 434 capturedAndBoxed = other.capturedAndBoxed, |
| 431 tryBlock = other.tryBlock, | 435 tryBlock = other.tryBlock, |
| 432 types = other.types, | 436 types = other.types, |
| 433 inferrer = other.inferrer, | 437 inferrer = other.inferrer, |
| 434 compiler = other.compiler; | 438 options = other.options; |
| 435 | 439 |
| 436 T use(Local local) { | 440 T use(Local local) { |
| 437 if (capturedAndBoxed.containsKey(local)) { | 441 if (capturedAndBoxed.containsKey(local)) { |
| 438 return inferrer.typeOfElement(capturedAndBoxed[local]); | 442 return inferrer.typeOfElement(capturedAndBoxed[local]); |
| 439 } else { | 443 } else { |
| 440 if (captured.containsKey(local)) { | 444 if (captured.containsKey(local)) { |
| 441 inferrer.recordCapturedLocalRead(local); | 445 inferrer.recordCapturedLocalRead(local); |
| 442 } | 446 } |
| 443 return locals[local]; | 447 return locals[local]; |
| 444 } | 448 } |
| 445 } | 449 } |
| 446 | 450 |
| 447 void update(LocalElement local, T type, Node node) { | 451 void update(LocalElement local, T type, Node node) { |
| 448 assert(type != null); | 452 assert(type != null); |
| 449 if (compiler.options.trustTypeAnnotations || | 453 if (options.trustTypeAnnotations || options.enableTypeAssertions) { |
| 450 compiler.options.enableTypeAssertions) { | |
| 451 type = types.narrowType(type, local.type); | 454 type = types.narrowType(type, local.type); |
| 452 } | 455 } |
| 453 updateLocal() { | 456 updateLocal() { |
| 454 T currentType = locals[local]; | 457 T currentType = locals[local]; |
| 455 | 458 |
| 456 SendSet send = node != null ? node.asSendSet() : null; | 459 SendSet send = node != null ? node.asSendSet() : null; |
| 457 if (send != null && send.isIfNullAssignment && currentType != null) { | 460 if (send != null && send.isIfNullAssignment && currentType != null) { |
| 458 // If-null assignments may return either the new or the original value | 461 // If-null assignments may return either the new or the original value |
| 459 // narrowed to non-null. | 462 // narrowed to non-null. |
| 460 type = types.addPhiInput( | 463 type = types.addPhiInput( |
| (...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 739 this.locals = handler { | 742 this.locals = handler { |
| 740 if (handler != null) return; | 743 if (handler != null) return; |
| 741 Node node; | 744 Node node; |
| 742 if (resolvedAst.kind == ResolvedAstKind.PARSED) { | 745 if (resolvedAst.kind == ResolvedAstKind.PARSED) { |
| 743 node = resolvedAst.node; | 746 node = resolvedAst.node; |
| 744 } | 747 } |
| 745 FieldInitializationScope<T> fieldScope = | 748 FieldInitializationScope<T> fieldScope = |
| 746 analyzedElement.isGenerativeConstructor | 749 analyzedElement.isGenerativeConstructor |
| 747 ? new FieldInitializationScope<T>(types) | 750 ? new FieldInitializationScope<T>(types) |
| 748 : null; | 751 : null; |
| 749 locals = new LocalsHandler<T>(inferrer, types, compiler, node, fieldScope); | 752 locals = new LocalsHandler<T>( |
| 753 inferrer, types, compiler.options, node, fieldScope); |
| 750 } | 754 } |
| 751 | 755 |
| 752 DiagnosticReporter get reporter => compiler.reporter; | 756 DiagnosticReporter get reporter => compiler.reporter; |
| 753 | 757 |
| 754 ClosedWorld get closedWorld => compiler.closedWorld; | 758 ClosedWorld get closedWorld => inferrer.closedWorld; |
| 755 | 759 |
| 756 @override | 760 @override |
| 757 SemanticSendVisitor get sendVisitor => this; | 761 SemanticSendVisitor get sendVisitor => this; |
| 758 | 762 |
| 759 @override | 763 @override |
| 760 T apply(Node node, _) => visit(node); | 764 T apply(Node node, _) => visit(node); |
| 761 | 765 |
| 762 T handleSendSet(SendSet node); | 766 T handleSendSet(SendSet node); |
| 763 | 767 |
| 764 T handleDynamicInvoke(Send node); | 768 T handleDynamicInvoke(Send node); |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 880 } | 884 } |
| 881 | 885 |
| 882 T visitLiteralNull(LiteralNull node) { | 886 T visitLiteralNull(LiteralNull node) { |
| 883 return types.nullType; | 887 return types.nullType; |
| 884 } | 888 } |
| 885 | 889 |
| 886 T visitLiteralSymbol(LiteralSymbol node) { | 890 T visitLiteralSymbol(LiteralSymbol node) { |
| 887 // TODO(kasperl): We should be able to tell that the type of a literal | 891 // TODO(kasperl): We should be able to tell that the type of a literal |
| 888 // symbol is always a non-null exact symbol implementation -- not just | 892 // symbol is always a non-null exact symbol implementation -- not just |
| 889 // any non-null subtype of the symbol interface. | 893 // any non-null subtype of the symbol interface. |
| 890 return types.nonNullSubtype(compiler.coreClasses.symbolClass); | 894 return types.nonNullSubtype(closedWorld.coreClasses.symbolClass); |
| 891 } | 895 } |
| 892 | 896 |
| 893 @override | 897 @override |
| 894 void previsitDeferredAccess(Send node, PrefixElement prefix, _) { | 898 void previsitDeferredAccess(Send node, PrefixElement prefix, _) { |
| 895 // Deferred access does not affect inference. | 899 // Deferred access does not affect inference. |
| 896 } | 900 } |
| 897 | 901 |
| 898 T handleTypeLiteralGet() { | 902 T handleTypeLiteralGet() { |
| 899 return types.typeType; | 903 return types.typeType; |
| 900 } | 904 } |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1031 (operator == '!=' && !usePositive)) { | 1035 (operator == '!=' && !usePositive)) { |
| 1032 // Type the elements as null. | 1036 // Type the elements as null. |
| 1033 if (Elements.isLocal(receiverElement)) { | 1037 if (Elements.isLocal(receiverElement)) { |
| 1034 locals.update(receiverElement, types.nullType, node); | 1038 locals.update(receiverElement, types.nullType, node); |
| 1035 } | 1039 } |
| 1036 if (Elements.isLocal(argumentElement)) { | 1040 if (Elements.isLocal(argumentElement)) { |
| 1037 locals.update(argumentElement, types.nullType, node); | 1041 locals.update(argumentElement, types.nullType, node); |
| 1038 } | 1042 } |
| 1039 } else { | 1043 } else { |
| 1040 // Narrow the elements to a non-null type. | 1044 // Narrow the elements to a non-null type. |
| 1041 DartType objectType = compiler.coreTypes.objectType; | 1045 DartType objectType = closedWorld.coreTypes.objectType; |
| 1042 if (Elements.isLocal(receiverElement)) { | 1046 if (Elements.isLocal(receiverElement)) { |
| 1043 narrow(receiverElement, objectType, node); | 1047 narrow(receiverElement, objectType, node); |
| 1044 } | 1048 } |
| 1045 if (Elements.isLocal(argumentElement)) { | 1049 if (Elements.isLocal(argumentElement)) { |
| 1046 narrow(argumentElement, objectType, node); | 1050 narrow(argumentElement, objectType, node); |
| 1047 } | 1051 } |
| 1048 } | 1052 } |
| 1049 } | 1053 } |
| 1050 } | 1054 } |
| 1051 } | 1055 } |
| (...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1491 return type; | 1495 return type; |
| 1492 } | 1496 } |
| 1493 | 1497 |
| 1494 T visitCascade(Cascade node) { | 1498 T visitCascade(Cascade node) { |
| 1495 // Ignore the result of the cascade send and return the type of the cascade | 1499 // Ignore the result of the cascade send and return the type of the cascade |
| 1496 // receiver. | 1500 // receiver. |
| 1497 visit(node.expression); | 1501 visit(node.expression); |
| 1498 return cascadeReceiverStack.removeLast(); | 1502 return cascadeReceiverStack.removeLast(); |
| 1499 } | 1503 } |
| 1500 } | 1504 } |
| OLD | NEW |