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

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

Issue 2516483002: fix #27336, ddc with recursive generic class type args (Closed)
Patch Set: Created 4 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 unified diff | Download patch
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 749 matching lines...) Expand 10 before | Expand all | Expand 10 after
760 760
761 var body = <JS.Statement>[]; 761 var body = <JS.Statement>[];
762 _initExtensionSymbols(classElem, methods, fields, body); 762 _initExtensionSymbols(classElem, methods, fields, body);
763 _emitSuperHelperSymbols(_superHelperSymbols, body); 763 _emitSuperHelperSymbols(_superHelperSymbols, body);
764 764
765 // Emit the class, e.g. `core.Object = class Object { ... }` 765 // Emit the class, e.g. `core.Object = class Object { ... }`
766 _defineClass(classElem, className, classExpr, isCallable, body); 766 _defineClass(classElem, className, classExpr, isCallable, body);
767 767
768 // Emit things that come after the ES6 `class ... { ... }`. 768 // Emit things that come after the ES6 `class ... { ... }`.
769 var jsPeerNames = _getJSPeerNames(classElem); 769 var jsPeerNames = _getJSPeerNames(classElem);
770 _setBaseClass(classElem, className, jsPeerNames, body); 770 JS.Statement deferredBaseClass =
771 _setBaseClass(classElem, className, jsPeerNames, body);
771 772
772 _emitClassTypeTests(classElem, className, body); 773 _emitClassTypeTests(classElem, className, body);
773 774
774 _defineNamedConstructors(ctors, body, className, isCallable); 775 _defineNamedConstructors(ctors, body, className, isCallable);
775 body.addAll(virtualFieldSymbols); 776 body.addAll(virtualFieldSymbols);
776 _emitClassSignature( 777 _emitClassSignature(
777 methods, allFields, classElem, ctors, extensions, className, body); 778 methods, allFields, classElem, ctors, extensions, className, body);
778 _defineExtensionMembers(extensions, className, body); 779 _defineExtensionMembers(extensions, className, body);
779 _emitClassMetadata(node.metadata, className, body); 780 _emitClassMetadata(node.metadata, className, body);
780 781
781 JS.Statement classDef = _statement(body); 782 JS.Statement classDef = _statement(body);
783
782 var typeFormals = classElem.typeParameters; 784 var typeFormals = classElem.typeParameters;
783 if (typeFormals.isNotEmpty) { 785 if (typeFormals.isNotEmpty) {
784 classDef = _defineClassTypeArguments(classElem, typeFormals, classDef); 786 classDef = _defineClassTypeArguments(
787 classElem, typeFormals, classDef, className, deferredBaseClass);
785 } 788 }
786 789
787 body = <JS.Statement>[classDef]; 790 body = <JS.Statement>[classDef];
788 _emitStaticFields(staticFields, staticFieldOverrides, classElem, body); 791 _emitStaticFields(staticFields, staticFieldOverrides, classElem, body);
789 for (var peer in jsPeerNames) { 792 for (var peer in jsPeerNames) {
790 _registerExtensionType(classElem, peer, body); 793 _registerExtensionType(classElem, peer, body);
791 } 794 }
792 return _statement(body); 795 return _statement(body);
793 } 796 }
794 797
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after
1119 id, 1122 id,
1120 new JS.ArrayInitializer(fields.map((f) => _propertyName(f.name)).toList(), 1123 new JS.ArrayInitializer(fields.map((f) => _propertyName(f.name)).toList(),
1121 multiline: true) 1124 multiline: true)
1122 ])); 1125 ]));
1123 1126
1124 return _statement(result); 1127 return _statement(result);
1125 } 1128 }
1126 1129
1127 /// Wraps a possibly generic class in its type arguments. 1130 /// Wraps a possibly generic class in its type arguments.
1128 JS.Statement _defineClassTypeArguments(TypeDefiningElement element, 1131 JS.Statement _defineClassTypeArguments(TypeDefiningElement element,
1129 List<TypeParameterElement> formals, JS.Statement body) { 1132 List<TypeParameterElement> formals, JS.Statement body,
1133 [JS.Expression className, JS.Statement deferredBaseClass]) {
1130 assert(formals.isNotEmpty); 1134 assert(formals.isNotEmpty);
1131 var genericCall = _callHelper('generic((#) => { #; #; return #; })', [ 1135 var typeConstructor = js.call('(#) => { #; #; return #; }', [
1132 _emitTypeFormals(formals), 1136 _emitTypeFormals(formals),
1133 _typeTable.discharge(formals), 1137 _typeTable.discharge(formals),
1134 body, 1138 body,
1135 element.name 1139 element.name
1136 ]); 1140 ]);
1141
1142 var genericArgs = [typeConstructor];
1143 if (deferredBaseClass != null) {
1144 genericArgs.add(js.call('(#) => { #; }', [className, deferredBaseClass]));
1145 }
1146
1147 var genericCall = _callHelper('generic(#)', [genericArgs]);
1148
1137 if (element.library.isDartAsync && 1149 if (element.library.isDartAsync &&
1138 (element.name == "Future" || element.name == "_Future")) { 1150 (element.name == "Future" || element.name == "_Future")) {
1139 genericCall = _callHelper('flattenFutures(#)', [genericCall]); 1151 genericCall = _callHelper('flattenFutures(#)', [genericCall]);
1140 } 1152 }
1141 var genericDef = js.statement( 1153 var genericDef = js.statement(
1142 '# = #;', [_emitTopLevelName(element, suffix: r'$'), genericCall]); 1154 '# = #;', [_emitTopLevelName(element, suffix: r'$'), genericCall]);
1143 var dynType = fillDynamicTypeArgs(element.type); 1155 var dynType = fillDynamicTypeArgs(element.type);
1144 var genericInst = _emitType(dynType, lowerGeneric: true); 1156 var genericInst = _emitType(dynType, lowerGeneric: true);
1145 return js.statement( 1157 return js.statement(
1146 '{ #; # = #; }', [genericDef, _emitTopLevelName(element), genericInst]); 1158 '{ #; # = #; }', [genericDef, _emitTopLevelName(element), genericInst]);
(...skipping 447 matching lines...) Expand 10 before | Expand all | Expand 10 after
1594 ClassElement classElem, String jsPeerName, List<JS.Statement> body) { 1606 ClassElement classElem, String jsPeerName, List<JS.Statement> body) {
1595 if (jsPeerName != null) { 1607 if (jsPeerName != null) {
1596 body.add(_callHelperStatement('registerExtension(#.global.#, #);', [ 1608 body.add(_callHelperStatement('registerExtension(#.global.#, #);', [
1597 _runtimeModule, 1609 _runtimeModule,
1598 _propertyName(jsPeerName), 1610 _propertyName(jsPeerName),
1599 _emitTopLevelName(classElem) 1611 _emitTopLevelName(classElem)
1600 ])); 1612 ]));
1601 } 1613 }
1602 } 1614 }
1603 1615
1604 void _setBaseClass(ClassElement classElem, JS.Expression className, 1616 JS.Statement _setBaseClass(ClassElement classElem, JS.Expression className,
1605 List<String> jsPeerNames, List<JS.Statement> body) { 1617 List<String> jsPeerNames, List<JS.Statement> body) {
1606 if (jsPeerNames.isNotEmpty && classElem.typeParameters.isNotEmpty) { 1618 var typeFormals = classElem.typeParameters;
1619 if (jsPeerNames.isNotEmpty && typeFormals.isNotEmpty) {
1607 for (var peer in jsPeerNames) { 1620 for (var peer in jsPeerNames) {
1608 // TODO(jmesserly): we should just extend Array in the first place 1621 // TODO(jmesserly): we should just extend Array in the first place
1609 var newBaseClass = _callHelper('global.#', [peer]); 1622 var newBaseClass = _callHelper('global.#', [peer]);
1610 body.add(_callHelperStatement( 1623 body.add(_callHelperStatement(
1611 'setExtensionBaseClass(#, #);', [className, newBaseClass])); 1624 'setExtensionBaseClass(#, #);', [className, newBaseClass]));
1612 } 1625 }
1613 } else if (_hasDeferredSupertype.contains(classElem)) { 1626 } else if (_hasDeferredSupertype.contains(classElem)) {
1614 var newBaseClass = _emitType(classElem.type.superclass, 1627 var newBaseClass = _emitType(classElem.type.superclass,
1615 nameType: false, subClass: classElem, className: className); 1628 nameType: false, subClass: classElem, className: className);
1616 body.add(_callHelperStatement( 1629 var deferredBaseClass = _callHelperStatement(
1617 'setBaseClass(#, #);', [className, newBaseClass])); 1630 'setBaseClass(#, #);', [className, newBaseClass]);
1631 if (typeFormals.isNotEmpty) return deferredBaseClass;
1632 body.add(deferredBaseClass);
1618 } 1633 }
1634 return null;
1619 } 1635 }
1620 1636
1621 void _defineNamedConstructors(List<ConstructorDeclaration> ctors, 1637 void _defineNamedConstructors(List<ConstructorDeclaration> ctors,
1622 List<JS.Statement> body, JS.Expression className, bool isCallable) { 1638 List<JS.Statement> body, JS.Expression className, bool isCallable) {
1623 var code = isCallable 1639 var code = isCallable
1624 ? 'defineNamedConstructorCallable(#, #, #);' 1640 ? 'defineNamedConstructorCallable(#, #, #);'
1625 : 'defineNamedConstructor(#, #)'; 1641 : 'defineNamedConstructor(#, #)';
1626 1642
1627 for (ConstructorDeclaration member in ctors) { 1643 for (ConstructorDeclaration member in ctors) {
1628 if (member.name != null && member.factoryKeyword == null) { 1644 if (member.name != null && member.factoryKeyword == null) {
(...skipping 1318 matching lines...) Expand 10 before | Expand all | Expand 10 after
2947 2963
2948 if (type is ParameterizedType) { 2964 if (type is ParameterizedType) {
2949 var args = type.typeArguments; 2965 var args = type.typeArguments;
2950 Iterable jsArgs = null; 2966 Iterable jsArgs = null;
2951 if (args.any((a) => !a.isDynamic)) { 2967 if (args.any((a) => !a.isDynamic)) {
2952 jsArgs = args.map((x) => _emitType(x, 2968 jsArgs = args.map((x) => _emitType(x,
2953 nameType: nameType, 2969 nameType: nameType,
2954 hoistType: hoistType, 2970 hoistType: hoistType,
2955 subClass: subClass, 2971 subClass: subClass,
2956 className: className)); 2972 className: className));
2957 } else if (lowerGeneric) { 2973 } else if (lowerGeneric || element == subClass) {
2958 jsArgs = []; 2974 jsArgs = [];
2959 } 2975 }
2960 if (jsArgs != null) { 2976 if (jsArgs != null) {
2961 var genericName = _emitTopLevelName(element, suffix: '\$'); 2977 var genericName = _emitTopLevelName(element, suffix: '\$');
2962 var typeRep = js.call('#(#)', [genericName, jsArgs]); 2978 var typeRep = js.call('#(#)', [genericName, jsArgs]);
2963 return nameType 2979 return nameType
2964 ? _typeTable.nameType(type, typeRep, hoistType: hoistType) 2980 ? _typeTable.nameType(type, typeRep, hoistType: hoistType)
2965 : typeRep; 2981 : typeRep;
2966 } 2982 }
2967 } 2983 }
(...skipping 2660 matching lines...) Expand 10 before | Expand all | Expand 10 after
5628 var targetIdentifier = target as SimpleIdentifier; 5644 var targetIdentifier = target as SimpleIdentifier;
5629 5645
5630 if (targetIdentifier.staticElement is! PrefixElement) return false; 5646 if (targetIdentifier.staticElement is! PrefixElement) return false;
5631 var prefix = targetIdentifier.staticElement as PrefixElement; 5647 var prefix = targetIdentifier.staticElement as PrefixElement;
5632 5648
5633 // The library the prefix is referring to must come from a deferred import. 5649 // The library the prefix is referring to must come from a deferred import.
5634 var containingLibrary = (target.root as CompilationUnit).element.library; 5650 var containingLibrary = (target.root as CompilationUnit).element.library;
5635 var imports = containingLibrary.getImportsWithPrefix(prefix); 5651 var imports = containingLibrary.getImportsWithPrefix(prefix);
5636 return imports.length == 1 && imports[0].isDeferred; 5652 return imports.length == 1 && imports[0].isDeferred;
5637 } 5653 }
OLDNEW
« no previous file with comments | « pkg/dev_compiler/lib/sdk/ddc_sdk.sum ('k') | pkg/dev_compiler/test/codegen/language/recursive_generic_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698