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

Side by Side Diff: pkg/dev_compiler/lib/src/compiler/code_generator.dart

Issue 2560983002: Support callable classes where call is inherited (Closed)
Patch Set: Created 4 years 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 unified diff | Download patch
« no previous file with comments | « no previous file | pkg/dev_compiler/test/codegen/language/callable_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 2
3 // for details. All rights reserved. Use of this source code is governed by a 3 // for details. All rights reserved. Use of this source code is governed by a
4 // BSD-style license that can be found in the LICENSE file. 4 // BSD-style license that can be found in the LICENSE file.
5 5
6 import 'dart:collection' show HashMap, HashSet; 6 import 'dart:collection' show HashMap, HashSet;
7 import 'dart:math' show min, max; 7 import 'dart:math' show min, max;
8 8
9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator;
10 import 'package:analyzer/dart/ast/ast.dart'; 10 import 'package:analyzer/dart/ast/ast.dart';
(...skipping 734 matching lines...) Expand 10 before | Expand all | Expand 10 after
745 745
746 // If this is a JavaScript type, emit it now and then exit. 746 // If this is a JavaScript type, emit it now and then exit.
747 var jsTypeDef = _emitJsType(classElem); 747 var jsTypeDef = _emitJsType(classElem);
748 if (jsTypeDef != null) return jsTypeDef; 748 if (jsTypeDef != null) return jsTypeDef;
749 749
750 var ctors = <ConstructorDeclaration>[]; 750 var ctors = <ConstructorDeclaration>[];
751 var fields = <FieldDeclaration>[]; 751 var fields = <FieldDeclaration>[];
752 var staticFields = <FieldDeclaration>[]; 752 var staticFields = <FieldDeclaration>[];
753 var methods = <MethodDeclaration>[]; 753 var methods = <MethodDeclaration>[];
754 754
755 // True if a "call" method or getter exists. 755 // True if a "call" method or getter exists directly on this class.
756 // If so, we need to install a Function prototype.
756 bool isCallable = false; 757 bool isCallable = false;
757 for (var member in node.members) { 758 for (var member in node.members) {
758 if (member is ConstructorDeclaration) { 759 if (member is ConstructorDeclaration) {
759 ctors.add(member); 760 ctors.add(member);
760 } else if (member is FieldDeclaration) { 761 } else if (member is FieldDeclaration) {
761 (member.isStatic ? staticFields : fields).add(member); 762 (member.isStatic ? staticFields : fields).add(member);
762 } else if (member is MethodDeclaration) { 763 } else if (member is MethodDeclaration) {
763 methods.add(member); 764 methods.add(member);
764 if (member.name.name == 'call' && !member.isSetter) { 765 if (member.name.name == 'call' && !member.isSetter) {
765 // 766 //
766 // Make sure "call" has a statically known function type: 767 // Make sure "call" has a statically known function type:
767 // 768 //
768 // - if it's a method, then it does because all methods do, 769 // - if it's a method, then it does because all methods do,
769 // - if it's a getter, check the return type. 770 // - if it's a getter, check the return type.
770 // 771 //
771 // Other cases like a getter returning dynamic/Object/Function will be 772 // Other cases like a getter returning dynamic/Object/Function will be
772 // handled at runtime by the dynamic call mechanism. So we only 773 // handled at runtime by the dynamic call mechanism. So we only
773 // concern ourselves with statically known function types. 774 // concern ourselves with statically known function types.
774 // 775 //
775 // For the same reason, we can ignore "noSuchMethod". 776 // For the same reason, we can ignore "noSuchMethod".
776 // call-implemented-by-nSM will be dispatched by dcall at runtime. 777 // call-implemented-by-nSM will be dispatched by dcall at runtime.
777 // 778 //
778 isCallable = !member.isGetter || member.returnType is FunctionType; 779 isCallable = !member.isGetter || member.returnType is FunctionType;
779 } 780 }
780 } 781 }
781 } 782 }
782 783
784 // True if a "call" method or getter exists directly or indirectly on this
785 // class. If so, we need special constructor handling.
786 bool isCallableTransitive =
787 classElem.lookUpMethod('call', currentLibrary) != null;
788 if (!isCallableTransitive) {
789 var callGetter = classElem.lookUpGetter('call', currentLibrary);
790 isCallableTransitive =
791 callGetter != null && callGetter.returnType is FunctionType;
792 }
793
783 JS.Expression className; 794 JS.Expression className;
784 if (classElem.typeParameters.isNotEmpty) { 795 if (classElem.typeParameters.isNotEmpty) {
785 // Generic classes will be defined inside a function that closes over the 796 // Generic classes will be defined inside a function that closes over the
786 // type parameter. So we can use their local variable name directly. 797 // type parameter. So we can use their local variable name directly.
787 className = new JS.Identifier(classElem.name); 798 className = new JS.Identifier(classElem.name);
788 } else { 799 } else {
789 className = _emitTopLevelName(classElem); 800 className = _emitTopLevelName(classElem);
790 } 801 }
791 802
792 var allFields = fields.toList()..addAll(staticFields); 803 var allFields = fields.toList()..addAll(staticFields);
(...skipping 16 matching lines...) Expand all
809 // Emit the class, e.g. `core.Object = class Object { ... }` 820 // Emit the class, e.g. `core.Object = class Object { ... }`
810 _defineClass(classElem, className, classExpr, isCallable, body); 821 _defineClass(classElem, className, classExpr, isCallable, body);
811 822
812 // Emit things that come after the ES6 `class ... { ... }`. 823 // Emit things that come after the ES6 `class ... { ... }`.
813 var jsPeerNames = _getJSPeerNames(classElem); 824 var jsPeerNames = _getJSPeerNames(classElem);
814 JS.Statement deferredBaseClass = 825 JS.Statement deferredBaseClass =
815 _setBaseClass(classElem, className, jsPeerNames, body); 826 _setBaseClass(classElem, className, jsPeerNames, body);
816 827
817 _emitClassTypeTests(classElem, className, body); 828 _emitClassTypeTests(classElem, className, body);
818 829
819 _defineNamedConstructors(ctors, body, className, isCallable); 830 _defineNamedConstructors(ctors, body, className, isCallableTransitive);
820 body.addAll(virtualFieldSymbols); 831 body.addAll(virtualFieldSymbols);
821 _emitClassSignature( 832 _emitClassSignature(
822 methods, allFields, classElem, ctors, extensions, className, body); 833 methods, allFields, classElem, ctors, extensions, className, body);
823 _defineExtensionMembers(extensions, className, body); 834 _defineExtensionMembers(extensions, className, body);
824 _emitClassMetadata(node.metadata, className, body); 835 _emitClassMetadata(node.metadata, className, body);
825 836
826 JS.Statement classDef = _statement(body); 837 JS.Statement classDef = _statement(body);
827 838
828 var typeFormals = classElem.typeParameters; 839 var typeFormals = classElem.typeParameters;
829 if (typeFormals.isNotEmpty) { 840 if (typeFormals.isNotEmpty) {
(...skipping 4969 matching lines...) Expand 10 before | Expand all | Expand 10 after
5799 if (targetIdentifier.staticElement is! PrefixElement) return false; 5810 if (targetIdentifier.staticElement is! PrefixElement) return false;
5800 var prefix = targetIdentifier.staticElement as PrefixElement; 5811 var prefix = targetIdentifier.staticElement as PrefixElement;
5801 5812
5802 // The library the prefix is referring to must come from a deferred import. 5813 // The library the prefix is referring to must come from a deferred import.
5803 var containingLibrary = resolutionMap 5814 var containingLibrary = resolutionMap
5804 .elementDeclaredByCompilationUnit(target.root as CompilationUnit) 5815 .elementDeclaredByCompilationUnit(target.root as CompilationUnit)
5805 .library; 5816 .library;
5806 var imports = containingLibrary.getImportsWithPrefix(prefix); 5817 var imports = containingLibrary.getImportsWithPrefix(prefix);
5807 return imports.length == 1 && imports[0].isDeferred; 5818 return imports.length == 1 && imports[0].isDeferred;
5808 } 5819 }
OLDNEW
« no previous file with comments | « no previous file | pkg/dev_compiler/test/codegen/language/callable_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698