| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 import '../common.dart'; | 5 import '../common.dart'; |
| 6 import '../common/backend_api.dart' show BackendClasses, ForeignResolver; | 6 import '../common/backend_api.dart' show BackendClasses, ForeignResolver; |
| 7 import '../common/resolution.dart' show ParsingContext, Resolution; | 7 import '../common/resolution.dart' show ParsingContext, Resolution; |
| 8 import '../compiler.dart' show Compiler; | 8 import '../compiler.dart' show Compiler; |
| 9 import '../compile_time_constants.dart' show ConstantEnvironment; | 9 import '../compile_time_constants.dart' show ConstantEnvironment; |
| 10 import '../constants/expressions.dart'; | 10 import '../constants/expressions.dart'; |
| 11 import '../constants/values.dart'; | 11 import '../constants/values.dart'; |
| 12 import '../core_types.dart' show CommonElements; | 12 import '../core_types.dart' show CommonElements; |
| 13 import '../elements/elements.dart'; | 13 import '../elements/elements.dart'; |
| 14 import '../elements/entities.dart'; | 14 import '../elements/entities.dart'; |
| 15 import '../elements/resolution_types.dart'; | 15 import '../elements/resolution_types.dart'; |
| 16 import '../elements/types.dart'; | 16 import '../elements/types.dart'; |
| 17 import '../js/js.dart' as js; | 17 import '../js/js.dart' as js; |
| 18 import '../js_backend/js_backend.dart'; | 18 import '../js_backend/js_backend.dart'; |
| 19 import '../js_backend/backend_helpers.dart'; | 19 import '../js_backend/backend_helpers.dart'; |
| 20 import '../options.dart'; | 20 import '../options.dart'; |
| 21 import '../tree/tree.dart'; | 21 import '../tree/tree.dart'; |
| 22 import '../universe/side_effects.dart' show SideEffects; | 22 import '../universe/side_effects.dart' show SideEffects; |
| 23 import '../util/util.dart'; | 23 import '../util/util.dart'; |
| 24 import 'js.dart'; | 24 import 'js.dart'; |
| 25 | 25 |
| 26 typedef dynamic /*DartType|SpecialType*/ TypeLookup(String typeString); | 26 typedef dynamic /*DartType|SpecialType*/ TypeLookup(String typeString, |
| 27 {bool required}); |
| 27 | 28 |
| 28 /// This class is a temporary work-around until we get a more powerful DartType. | 29 /// This class is a temporary work-around until we get a more powerful DartType. |
| 29 class SpecialType { | 30 class SpecialType { |
| 30 final String name; | 31 final String name; |
| 31 const SpecialType._(this.name); | 32 const SpecialType._(this.name); |
| 32 | 33 |
| 33 /// The type Object, but no subtypes: | 34 /// The type Object, but no subtypes: |
| 34 static const JsObject = const SpecialType._('=Object'); | 35 static const JsObject = const SpecialType._('=Object'); |
| 35 | 36 |
| 36 int get hashCode => name.hashCode; | 37 int get hashCode => name.hashCode; |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 310 } | 311 } |
| 311 return; | 312 return; |
| 312 } | 313 } |
| 313 if (typesString == '' || typesString == 'var') { | 314 if (typesString == '' || typesString == 'var') { |
| 314 if (onVar != null) { | 315 if (onVar != null) { |
| 315 onVar(); | 316 onVar(); |
| 316 } | 317 } |
| 317 return; | 318 return; |
| 318 } | 319 } |
| 319 for (final typeString in typesString.split('|')) { | 320 for (final typeString in typesString.split('|')) { |
| 320 onType(_parseType(typeString.trim(), spannable, reporter, lookupType)); | 321 onType(_parseType(typeString.trim(), lookupType)); |
| 321 } | 322 } |
| 322 } | 323 } |
| 323 | 324 |
| 324 if (!specString.contains(';') && !specString.contains(':')) { | 325 if (!specString.contains(';') && !specString.contains(':')) { |
| 325 // Form (1), types or pseudo-types like 'void' and 'var'. | 326 // Form (1), types or pseudo-types like 'void' and 'var'. |
| 326 resolveTypesString(specString.trim(), onVar: () { | 327 resolveTypesString(specString.trim(), onVar: () { |
| 327 typesReturned.add(objectType); | 328 typesReturned.add(objectType); |
| 328 typesReturned.add(nullType); | 329 typesReturned.add(nullType); |
| 329 }, onType: (type) { | 330 }, onType: (type) { |
| 330 typesInstantiated.add(type); | 331 typesInstantiated.add(type); |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 492 reportError("Unrecognized side-effect flag: '$dependency'."); | 493 reportError("Unrecognized side-effect flag: '$dependency'."); |
| 493 } | 494 } |
| 494 } | 495 } |
| 495 } | 496 } |
| 496 | 497 |
| 497 return sideEffects; | 498 return sideEffects; |
| 498 } | 499 } |
| 499 | 500 |
| 500 /// Returns a [TypeLookup] that uses [resolver] to perform lookup and [node] | 501 /// Returns a [TypeLookup] that uses [resolver] to perform lookup and [node] |
| 501 /// as position for errors. | 502 /// as position for errors. |
| 502 static TypeLookup _typeLookup(Node node, ForeignResolver resolver) { | 503 static TypeLookup _typeLookup( |
| 503 return (String name) => resolver.resolveTypeFromString(node, name); | 504 Node node, DiagnosticReporter reporter, ForeignResolver resolver) { |
| 505 ResolutionDartType lookup(String name, {bool required}) { |
| 506 ResolutionDartType type = resolver.resolveTypeFromString(node, name); |
| 507 if (type == null && required) { |
| 508 reporter.reportErrorMessage( |
| 509 node, MessageKind.GENERIC, {'text': "Type '$name' not found."}); |
| 510 } |
| 511 return type; |
| 512 } |
| 513 |
| 514 return lookup; |
| 504 } | 515 } |
| 505 | 516 |
| 506 /// Compute the [NativeBehavior] for a [Send] node calling the 'JS' function. | 517 /// Compute the [NativeBehavior] for a [Send] node calling the 'JS' function. |
| 507 static NativeBehavior ofJsCallSend( | 518 static NativeBehavior ofJsCallSend( |
| 508 Send jsCall, | 519 Send jsCall, |
| 509 DiagnosticReporter reporter, | 520 DiagnosticReporter reporter, |
| 510 ParsingContext parsing, | 521 ParsingContext parsing, |
| 511 CommonElements commonElements, | 522 CommonElements commonElements, |
| 512 ForeignResolver resolver) { | 523 ForeignResolver resolver) { |
| 513 var argNodes = jsCall.arguments; | 524 var argNodes = jsCall.arguments; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 526 var codeArgument = argNodes.tail.head; | 537 var codeArgument = argNodes.tail.head; |
| 527 if (codeArgument is! StringNode || codeArgument.isInterpolation) { | 538 if (codeArgument is! StringNode || codeArgument.isInterpolation) { |
| 528 reporter.reportErrorMessage( | 539 reporter.reportErrorMessage( |
| 529 codeArgument, MessageKind.WRONG_ARGUMENT_FOR_JS_SECOND); | 540 codeArgument, MessageKind.WRONG_ARGUMENT_FOR_JS_SECOND); |
| 530 return new NativeBehavior(); | 541 return new NativeBehavior(); |
| 531 } | 542 } |
| 532 | 543 |
| 533 String specString = specArgument.dartString.slowToString(); | 544 String specString = specArgument.dartString.slowToString(); |
| 534 String codeString = codeArgument.dartString.slowToString(); | 545 String codeString = codeArgument.dartString.slowToString(); |
| 535 | 546 |
| 536 return ofJsCall(specString, codeString, _typeLookup(specArgument, resolver), | 547 return ofJsCall( |
| 537 specArgument, reporter, commonElements); | 548 specString, |
| 549 codeString, |
| 550 _typeLookup(specArgument, reporter, resolver), |
| 551 specArgument, |
| 552 reporter, |
| 553 commonElements); |
| 538 } | 554 } |
| 539 | 555 |
| 540 /// Compute the [NativeBehavior] for a call to the 'JS' function with the | 556 /// Compute the [NativeBehavior] for a call to the 'JS' function with the |
| 541 /// given [specString] and [codeString] (first and second arguments). | 557 /// given [specString] and [codeString] (first and second arguments). |
| 542 static NativeBehavior ofJsCall( | 558 static NativeBehavior ofJsCall( |
| 543 String specString, | 559 String specString, |
| 544 String codeString, | 560 String codeString, |
| 545 TypeLookup lookupType, | 561 TypeLookup lookupType, |
| 546 Spannable spannable, | 562 Spannable spannable, |
| 547 DiagnosticReporter reporter, | 563 DiagnosticReporter reporter, |
| (...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 652 | 668 |
| 653 LiteralString specLiteral = argNodes.head.asLiteralString(); | 669 LiteralString specLiteral = argNodes.head.asLiteralString(); |
| 654 if (specLiteral == null) { | 670 if (specLiteral == null) { |
| 655 // TODO(sra): We could accept a type identifier? e.g. JS(bool, '1<2'). It | 671 // TODO(sra): We could accept a type identifier? e.g. JS(bool, '1<2'). It |
| 656 // is not very satisfactory because it does not work for void, dynamic. | 672 // is not very satisfactory because it does not work for void, dynamic. |
| 657 reporter.internalError(argNodes.head, "Unexpected first argument."); | 673 reporter.internalError(argNodes.head, "Unexpected first argument."); |
| 658 } | 674 } |
| 659 | 675 |
| 660 String specString = specLiteral.dartString.slowToString(); | 676 String specString = specLiteral.dartString.slowToString(); |
| 661 | 677 |
| 662 return ofJsBuiltinCall(specString, _typeLookup(jsBuiltinCall, resolver), | 678 return ofJsBuiltinCall( |
| 663 jsBuiltinCall, reporter, commonElements); | 679 specString, |
| 680 _typeLookup(jsBuiltinCall, reporter, resolver), |
| 681 jsBuiltinCall, |
| 682 reporter, |
| 683 commonElements); |
| 664 } | 684 } |
| 665 | 685 |
| 666 static NativeBehavior ofJsBuiltinCall( | 686 static NativeBehavior ofJsBuiltinCall( |
| 667 String specString, | 687 String specString, |
| 668 TypeLookup lookupType, | 688 TypeLookup lookupType, |
| 669 Spannable spannable, | 689 Spannable spannable, |
| 670 DiagnosticReporter reporter, | 690 DiagnosticReporter reporter, |
| 671 CommonElements commonElements) { | 691 CommonElements commonElements) { |
| 672 NativeBehavior behavior = new NativeBehavior(); | 692 NativeBehavior behavior = new NativeBehavior(); |
| 673 behavior.sideEffects.setTo(new SideEffects()); | 693 behavior.sideEffects.setTo(new SideEffects()); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 717 if (specLiteral == null) { | 737 if (specLiteral == null) { |
| 718 // TODO(sra): We could accept a type identifier? e.g. JS(bool, '1<2'). It | 738 // TODO(sra): We could accept a type identifier? e.g. JS(bool, '1<2'). It |
| 719 // is not very satisfactory because it does not work for void, dynamic. | 739 // is not very satisfactory because it does not work for void, dynamic. |
| 720 reporter.internalError(argNodes.head, "Unexpected first argument."); | 740 reporter.internalError(argNodes.head, "Unexpected first argument."); |
| 721 } | 741 } |
| 722 | 742 |
| 723 String specString = specLiteral.dartString.slowToString(); | 743 String specString = specLiteral.dartString.slowToString(); |
| 724 | 744 |
| 725 return ofJsEmbeddedGlobalCall( | 745 return ofJsEmbeddedGlobalCall( |
| 726 specString, | 746 specString, |
| 727 _typeLookup(jsEmbeddedGlobalCall, resolver), | 747 _typeLookup(jsEmbeddedGlobalCall, reporter, resolver), |
| 728 jsEmbeddedGlobalCall, | 748 jsEmbeddedGlobalCall, |
| 729 reporter, | 749 reporter, |
| 730 commonElements); | 750 commonElements); |
| 731 } | 751 } |
| 732 | 752 |
| 733 static NativeBehavior ofJsEmbeddedGlobalCall( | 753 static NativeBehavior ofJsEmbeddedGlobalCall( |
| 734 String specString, | 754 String specString, |
| 735 TypeLookup lookupType, | 755 TypeLookup lookupType, |
| 736 Spannable spannable, | 756 Spannable spannable, |
| 737 DiagnosticReporter reporter, | 757 DiagnosticReporter reporter, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 750 | 770 |
| 751 static NativeBehavior ofMethodElement( | 771 static NativeBehavior ofMethodElement( |
| 752 FunctionElement element, Compiler compiler) { | 772 FunctionElement element, Compiler compiler) { |
| 753 ResolutionFunctionType type = element.computeType(compiler.resolution); | 773 ResolutionFunctionType type = element.computeType(compiler.resolution); |
| 754 List<ConstantExpression> metadata = <ConstantExpression>[]; | 774 List<ConstantExpression> metadata = <ConstantExpression>[]; |
| 755 for (MetadataAnnotation annotation in element.implementation.metadata) { | 775 for (MetadataAnnotation annotation in element.implementation.metadata) { |
| 756 annotation.ensureResolved(compiler.resolution); | 776 annotation.ensureResolved(compiler.resolution); |
| 757 metadata.add(annotation.constant); | 777 metadata.add(annotation.constant); |
| 758 } | 778 } |
| 759 | 779 |
| 760 ResolutionDartType lookup(String name) { | |
| 761 Element e = element.buildScope().lookup(name); | |
| 762 if (e == null) return null; | |
| 763 if (e is! ClassElement) return null; | |
| 764 ClassElement cls = e; | |
| 765 cls.ensureResolved(compiler.resolution); | |
| 766 return cls.thisType; | |
| 767 } | |
| 768 | |
| 769 BehaviorBuilder builder = new ResolverBehaviorBuilder(compiler); | 780 BehaviorBuilder builder = new ResolverBehaviorBuilder(compiler); |
| 770 return builder.buildMethodBehavior(type, metadata, lookup, | 781 return builder.buildMethodBehavior( |
| 782 type, metadata, lookupFromElement(compiler.resolution, element), |
| 771 isJsInterop: compiler.backend.isJsInterop(element)); | 783 isJsInterop: compiler.backend.isJsInterop(element)); |
| 772 } | 784 } |
| 773 | 785 |
| 774 static NativeBehavior ofFieldElementLoad( | 786 static NativeBehavior ofFieldElementLoad( |
| 775 MemberElement element, Compiler compiler) { | 787 MemberElement element, Compiler compiler) { |
| 776 Resolution resolution = compiler.resolution; | 788 Resolution resolution = compiler.resolution; |
| 777 ResolutionDartType type = element.computeType(resolution); | 789 ResolutionDartType type = element.computeType(resolution); |
| 778 List<ConstantExpression> metadata = <ConstantExpression>[]; | 790 List<ConstantExpression> metadata = <ConstantExpression>[]; |
| 779 for (MetadataAnnotation annotation in element.implementation.metadata) { | 791 for (MetadataAnnotation annotation in element.implementation.metadata) { |
| 780 annotation.ensureResolved(compiler.resolution); | 792 annotation.ensureResolved(compiler.resolution); |
| 781 metadata.add(annotation.constant); | 793 metadata.add(annotation.constant); |
| 782 } | 794 } |
| 783 | 795 |
| 784 ResolutionDartType lookup(String name) { | |
| 785 Element e = element.buildScope().lookup(name); | |
| 786 if (e == null) return null; | |
| 787 if (e is! ClassElement) return null; | |
| 788 ClassElement cls = e; | |
| 789 cls.ensureResolved(compiler.resolution); | |
| 790 return cls.thisType; | |
| 791 } | |
| 792 | |
| 793 BehaviorBuilder builder = new ResolverBehaviorBuilder(compiler); | 796 BehaviorBuilder builder = new ResolverBehaviorBuilder(compiler); |
| 794 return builder.buildFieldLoadBehavior(type, metadata, lookup, | 797 return builder.buildFieldLoadBehavior( |
| 798 type, metadata, lookupFromElement(resolution, element), |
| 795 isJsInterop: compiler.backend.isJsInterop(element)); | 799 isJsInterop: compiler.backend.isJsInterop(element)); |
| 796 } | 800 } |
| 797 | 801 |
| 798 static NativeBehavior ofFieldElementStore( | 802 static NativeBehavior ofFieldElementStore( |
| 799 MemberElement field, Compiler compiler) { | 803 MemberElement field, Compiler compiler) { |
| 800 BehaviorBuilder builder = new ResolverBehaviorBuilder(compiler); | 804 BehaviorBuilder builder = new ResolverBehaviorBuilder(compiler); |
| 801 ResolutionDartType type = field.computeType(compiler.resolution); | 805 ResolutionDartType type = field.computeType(compiler.resolution); |
| 802 return builder.buildFieldStoreBehavior(type); | 806 return builder.buildFieldStoreBehavior(type); |
| 803 } | 807 } |
| 804 | 808 |
| 805 static dynamic /*DartType|SpecialType*/ _parseType(String typeString, | 809 static TypeLookup lookupFromElement(Resolution resolution, Element element) { |
| 806 Spannable spannable, DiagnosticReporter reporter, TypeLookup lookupType) { | 810 ResolutionDartType lookup(String name, {bool required}) { |
| 811 Element e = element.buildScope().lookup(name); |
| 812 if (e == null || e is! ClassElement) { |
| 813 if (required) { |
| 814 resolution.reporter.reportErrorMessage(element, MessageKind.GENERIC, |
| 815 {'text': "Type '$name' not found."}); |
| 816 } |
| 817 return null; |
| 818 } |
| 819 ClassElement cls = e; |
| 820 cls.ensureResolved(resolution); |
| 821 return cls.thisType; |
| 822 } |
| 823 |
| 824 return lookup; |
| 825 } |
| 826 |
| 827 static dynamic /*DartType|SpecialType*/ _parseType( |
| 828 String typeString, TypeLookup lookupType) { |
| 807 if (typeString == '=Object') return SpecialType.JsObject; | 829 if (typeString == '=Object') return SpecialType.JsObject; |
| 808 if (typeString == 'dynamic') { | 830 if (typeString == 'dynamic') { |
| 809 return const ResolutionDynamicType(); | 831 return const ResolutionDynamicType(); |
| 810 } | 832 } |
| 811 var type = lookupType(typeString); | 833 int index = typeString.indexOf('<'); |
| 834 var type = lookupType(typeString, required: index == -1); |
| 812 if (type != null) return type; | 835 if (type != null) return type; |
| 813 | 836 |
| 814 int index = typeString.indexOf('<'); | 837 if (index != -1) { |
| 815 if (index < 1) { | 838 type = lookupType(typeString.substring(0, index), required: true); |
| 816 reporter.reportErrorMessage(spannable, MessageKind.GENERIC, | 839 if (type != null) { |
| 817 {'text': "Type '$typeString' not found."}); | 840 // TODO(sra): Parse type parameters. |
| 818 return const ResolutionDynamicType(); | 841 return type; |
| 842 } |
| 819 } | 843 } |
| 820 type = lookupType(typeString.substring(0, index)); | |
| 821 if (type != null) { | |
| 822 // TODO(sra): Parse type parameters. | |
| 823 return type; | |
| 824 } | |
| 825 reporter.reportErrorMessage(spannable, MessageKind.GENERIC, | |
| 826 {'text': "Type '$typeString' not found."}); | |
| 827 return const ResolutionDynamicType(); | 844 return const ResolutionDynamicType(); |
| 828 } | 845 } |
| 829 } | 846 } |
| 830 | 847 |
| 831 abstract class BehaviorBuilder { | 848 abstract class BehaviorBuilder { |
| 832 CommonElements get commonElements; | 849 CommonElements get commonElements; |
| 833 BackendClasses get backendClasses; | 850 BackendClasses get backendClasses; |
| 834 BackendHelpers get helpers; | 851 BackendHelpers get helpers; |
| 835 DiagnosticReporter get reporter; | 852 DiagnosticReporter get reporter; |
| 836 ConstantEnvironment get constants; | 853 ConstantEnvironment get constants; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 877 | 894 |
| 878 Iterable<ConstantValue> fields = constructedObject.fields.values; | 895 Iterable<ConstantValue> fields = constructedObject.fields.values; |
| 879 // TODO(sra): Better validation of the constant. | 896 // TODO(sra): Better validation of the constant. |
| 880 if (fields.length != 1 || !fields.single.isString) { | 897 if (fields.length != 1 || !fields.single.isString) { |
| 881 reporter.internalError(CURRENT_ELEMENT_SPANNABLE, | 898 reporter.internalError(CURRENT_ELEMENT_SPANNABLE, |
| 882 'Annotations needs one string: ${constant.toStructuredText()}'); | 899 'Annotations needs one string: ${constant.toStructuredText()}'); |
| 883 } | 900 } |
| 884 StringConstantValue specStringConstant = fields.single; | 901 StringConstantValue specStringConstant = fields.single; |
| 885 String specString = specStringConstant.toDartString().slowToString(); | 902 String specString = specStringConstant.toDartString().slowToString(); |
| 886 for (final typeString in specString.split('|')) { | 903 for (final typeString in specString.split('|')) { |
| 887 var type = NativeBehavior._parseType( | 904 var type = NativeBehavior._parseType(typeString, lookupType); |
| 888 typeString, CURRENT_ELEMENT_SPANNABLE, reporter, lookupType); | |
| 889 if (types == null) types = []; | 905 if (types == null) types = []; |
| 890 types.add(type); | 906 types.add(type); |
| 891 } | 907 } |
| 892 } | 908 } |
| 893 return types; | 909 return types; |
| 894 } | 910 } |
| 895 | 911 |
| 896 /// Models the behavior of having intances of [type] escape from Dart code | 912 /// Models the behavior of having intances of [type] escape from Dart code |
| 897 /// into native code. | 913 /// into native code. |
| 898 void _escape(DartType type) { | 914 void _escape(DartType type) { |
| (...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1042 JavaScriptBackend backend = compiler.backend; | 1058 JavaScriptBackend backend = compiler.backend; |
| 1043 return backend.helpers; | 1059 return backend.helpers; |
| 1044 } | 1060 } |
| 1045 | 1061 |
| 1046 @override | 1062 @override |
| 1047 BackendClasses get backendClasses => compiler.backend.backendClasses; | 1063 BackendClasses get backendClasses => compiler.backend.backendClasses; |
| 1048 | 1064 |
| 1049 @override | 1065 @override |
| 1050 Resolution get resolution => compiler.resolution; | 1066 Resolution get resolution => compiler.resolution; |
| 1051 } | 1067 } |
| OLD | NEW |