OLD | NEW |
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 // 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 dev_compiler.src.codegen.js_codegen; | 5 library dev_compiler.src.codegen.js_codegen; |
6 | 6 |
7 import 'dart:collection' show HashSet, HashMap, SplayTreeSet; | 7 import 'dart:collection' show HashSet, HashMap, SplayTreeSet; |
8 | 8 |
9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
10 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; | 10 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; |
(...skipping 629 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
640 var sNames = []; | 640 var sNames = []; |
641 for (MethodDeclaration node in methods) { | 641 for (MethodDeclaration node in methods) { |
642 if (!(node.isSetter || node.isGetter || node.isAbstract)) { | 642 if (!(node.isSetter || node.isGetter || node.isAbstract)) { |
643 var name = node.name.name; | 643 var name = node.name.name; |
644 var element = node.element; | 644 var element = node.element; |
645 var inheritedElement = | 645 var inheritedElement = |
646 classElem.lookUpInheritedConcreteMethod(name, currentLibrary); | 646 classElem.lookUpInheritedConcreteMethod(name, currentLibrary); |
647 if (inheritedElement != null && | 647 if (inheritedElement != null && |
648 inheritedElement.type == element.type) continue; | 648 inheritedElement.type == element.type) continue; |
649 var memberName = _elementMemberName(element); | 649 var memberName = _elementMemberName(element); |
650 var parts = | 650 var parts = _emitFunctionTypeParts(element.type); |
651 _emitFunctionTypeParts(element.type, dynamicIsBottom: false); | |
652 var property = | 651 var property = |
653 new JS.Property(memberName, new JS.ArrayInitializer(parts)); | 652 new JS.Property(memberName, new JS.ArrayInitializer(parts)); |
654 if (node.isStatic) { | 653 if (node.isStatic) { |
655 tStatics.add(property); | 654 tStatics.add(property); |
656 sNames.add(memberName); | 655 sNames.add(memberName); |
657 } else { | 656 } else { |
658 tMethods.add(property); | 657 tMethods.add(property); |
659 } | 658 } |
660 } | 659 } |
661 } | 660 } |
662 | 661 |
663 var tCtors = []; | 662 var tCtors = []; |
664 for (ConstructorDeclaration node in ctors) { | 663 for (ConstructorDeclaration node in ctors) { |
665 var memberName = _constructorName(node.element); | 664 var memberName = _constructorName(node.element); |
666 var element = node.element; | 665 var element = node.element; |
667 var parts = | 666 var parts = _emitFunctionTypeParts(element.type); |
668 _emitFunctionTypeParts(element.type, dynamicIsBottom: false); | |
669 var property = | 667 var property = |
670 new JS.Property(memberName, new JS.ArrayInitializer(parts)); | 668 new JS.Property(memberName, new JS.ArrayInitializer(parts)); |
671 tCtors.add(property); | 669 tCtors.add(property); |
672 } | 670 } |
673 | 671 |
674 build(name, elements) { | 672 build(name, elements) { |
675 var o = | 673 var o = |
676 new JS.ObjectInitializer(elements, multiline: elements.length > 1); | 674 new JS.ObjectInitializer(elements, multiline: elements.length > 1); |
677 var e = js.call('() => #', o); | 675 var e = js.call('() => #', o); |
678 var p = new JS.Property(_propertyName(name), e); | 676 var p = new JS.Property(_propertyName(name), e); |
(...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1178 if (type is FunctionType && (name == '' || name == null)) { | 1176 if (type is FunctionType && (name == '' || name == null)) { |
1179 if (type.returnType.isDynamic && | 1177 if (type.returnType.isDynamic && |
1180 type.optionalParameterTypes.isEmpty && | 1178 type.optionalParameterTypes.isEmpty && |
1181 type.namedParameterTypes.isEmpty && | 1179 type.namedParameterTypes.isEmpty && |
1182 type.normalParameterTypes.every((t) => t.isDynamic)) { | 1180 type.normalParameterTypes.every((t) => t.isDynamic)) { |
1183 return js.call('dart.fn(#)', [clos]); | 1181 return js.call('dart.fn(#)', [clos]); |
1184 } | 1182 } |
1185 if (lazy) { | 1183 if (lazy) { |
1186 return js.call('dart.fn(#, () => #)', [clos, _emitFunctionRTTI(type)]); | 1184 return js.call('dart.fn(#, () => #)', [clos, _emitFunctionRTTI(type)]); |
1187 } | 1185 } |
1188 return js.call('dart.fn(#, #)', [ | 1186 return js.call('dart.fn(#, #)', [clos, _emitFunctionTypeParts(type)]); |
1189 clos, | |
1190 _emitFunctionTypeParts(type, dynamicIsBottom: false) | |
1191 ]); | |
1192 } | 1187 } |
1193 throw 'Function has non function type: $type'; | 1188 throw 'Function has non function type: $type'; |
1194 } | 1189 } |
1195 | 1190 |
1196 @override | 1191 @override |
1197 JS.Expression visitFunctionExpression(FunctionExpression node) { | 1192 JS.Expression visitFunctionExpression(FunctionExpression node) { |
1198 var params = _visit(node.parameters); | 1193 var params = _visit(node.parameters); |
1199 if (params == null) params = []; | 1194 if (params == null) params = []; |
1200 | 1195 |
1201 var parent = node.parent; | 1196 var parent = node.parent; |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1314 return _getTemp(element, name); | 1309 return _getTemp(element, name); |
1315 } | 1310 } |
1316 } | 1311 } |
1317 | 1312 |
1318 return new JS.Identifier(name); | 1313 return new JS.Identifier(name); |
1319 } | 1314 } |
1320 | 1315 |
1321 JS.TemporaryId _getTemp(Object key, String name) => | 1316 JS.TemporaryId _getTemp(Object key, String name) => |
1322 _temps.putIfAbsent(key, () => new JS.TemporaryId(name)); | 1317 _temps.putIfAbsent(key, () => new JS.TemporaryId(name)); |
1323 | 1318 |
1324 JS.ArrayInitializer _emitTypeNames(List<DartType> types, | 1319 JS.ArrayInitializer _emitTypeNames(List<DartType> types) { |
1325 {dynamicIsBottom: false}) { | 1320 var build = (t) => _emitTypeName(t); |
1326 var build = (t) => _emitTypeName(t, dynamicIsBottom: dynamicIsBottom); | |
1327 return new JS.ArrayInitializer(types.map(build).toList()); | 1321 return new JS.ArrayInitializer(types.map(build).toList()); |
1328 } | 1322 } |
1329 | 1323 |
1330 JS.ObjectInitializer _emitTypeProperties(Map<String, DartType> types, | 1324 JS.ObjectInitializer _emitTypeProperties(Map<String, DartType> types) { |
1331 {dynamicIsBottom: false}) { | |
1332 var properties = <JS.Property>[]; | 1325 var properties = <JS.Property>[]; |
1333 types.forEach((name, type) { | 1326 types.forEach((name, type) { |
1334 var key = _propertyName(name); | 1327 var key = _propertyName(name); |
1335 var value = _emitTypeName(type, dynamicIsBottom: dynamicIsBottom); | 1328 var value = _emitTypeName(type); |
1336 properties.add(new JS.Property(key, value)); | 1329 properties.add(new JS.Property(key, value)); |
1337 }); | 1330 }); |
1338 return new JS.ObjectInitializer(properties); | 1331 return new JS.ObjectInitializer(properties); |
1339 } | 1332 } |
1340 | 1333 |
1341 /// Emit the pieces of a function type, as an array of return type, | 1334 /// Emit the pieces of a function type, as an array of return type, |
1342 /// regular args, and optional/named args. | 1335 /// regular args, and optional/named args. |
1343 /// If [dynamicIsBottom] is true, then dynamics in argument positions | 1336 List<JS.Expression> _emitFunctionTypeParts(FunctionType type) { |
1344 /// will be lowered to bottom instead of Object. | |
1345 List<JS.Expression> _emitFunctionTypeParts(FunctionType type, | |
1346 {bool dynamicIsBottom: true}) { | |
1347 var returnType = type.returnType; | 1337 var returnType = type.returnType; |
1348 var parameterTypes = type.normalParameterTypes; | 1338 var parameterTypes = type.normalParameterTypes; |
1349 var optionalTypes = type.optionalParameterTypes; | 1339 var optionalTypes = type.optionalParameterTypes; |
1350 var namedTypes = type.namedParameterTypes; | 1340 var namedTypes = type.namedParameterTypes; |
1351 var rt = _emitTypeName(returnType); | 1341 var rt = _emitTypeName(returnType); |
1352 var ra = _emitTypeNames(parameterTypes, dynamicIsBottom: dynamicIsBottom); | 1342 var ra = _emitTypeNames(parameterTypes); |
1353 if (!namedTypes.isEmpty) { | 1343 if (!namedTypes.isEmpty) { |
1354 assert(optionalTypes.isEmpty); | 1344 assert(optionalTypes.isEmpty); |
1355 var na = | 1345 var na = _emitTypeProperties(namedTypes); |
1356 _emitTypeProperties(namedTypes, dynamicIsBottom: dynamicIsBottom); | |
1357 return [rt, ra, na]; | 1346 return [rt, ra, na]; |
1358 } | 1347 } |
1359 if (!optionalTypes.isEmpty) { | 1348 if (!optionalTypes.isEmpty) { |
1360 assert(namedTypes.isEmpty); | 1349 assert(namedTypes.isEmpty); |
1361 var oa = _emitTypeNames(optionalTypes, dynamicIsBottom: dynamicIsBottom); | 1350 var oa = _emitTypeNames(optionalTypes); |
1362 return [rt, ra, oa]; | 1351 return [rt, ra, oa]; |
1363 } | 1352 } |
1364 return [rt, ra]; | 1353 return [rt, ra]; |
1365 } | 1354 } |
1366 | 1355 |
1367 JS.Expression _emitFunctionRTTI(FunctionType type) { | 1356 JS.Expression _emitFunctionRTTI(FunctionType type) { |
1368 var parts = _emitFunctionTypeParts(type, dynamicIsBottom: false); | 1357 var parts = _emitFunctionTypeParts(type); |
1369 return js.call('dart.functionType(#)', [parts]); | 1358 return js.call('dart.definiteFunctionType(#)', [parts]); |
1370 } | 1359 } |
1371 | 1360 |
1372 /// Emits a Dart [type] into code. | 1361 /// Emits a Dart [type] into code. |
1373 /// | 1362 /// |
1374 /// If [lowerTypedef] is set, a typedef will be expanded as if it were a | 1363 /// If [lowerTypedef] is set, a typedef will be expanded as if it were a |
1375 /// function type. Similarly if [lowerGeneric] is set, the `List$()` form | 1364 /// function type. Similarly if [lowerGeneric] is set, the `List$()` form |
1376 /// will be used instead of `List`. These flags are used when generating | 1365 /// will be used instead of `List`. These flags are used when generating |
1377 /// the definitions for typedefs and generic types, respectively. | 1366 /// the definitions for typedefs and generic types, respectively. |
1378 JS.Expression _emitTypeName(DartType type, {bool lowerTypedef: false, | 1367 JS.Expression _emitTypeName(DartType type, |
1379 bool lowerGeneric: false, bool dynamicIsBottom: false}) { | 1368 {bool lowerTypedef: false, bool lowerGeneric: false}) { |
1380 | 1369 |
1381 // The void and dynamic types are not defined in core. | 1370 // The void and dynamic types are not defined in core. |
1382 if (type.isVoid) { | 1371 if (type.isVoid) { |
1383 return js.call('dart.void'); | 1372 return js.call('dart.void'); |
1384 } else if (type.isDynamic) { | 1373 } else if (type.isDynamic) { |
1385 if (dynamicIsBottom) return js.call('dart.bottom'); | 1374 return js.call('dart.dynamic'); |
1386 return _emitTypeName(types.objectType); | |
1387 } else if (type.isBottom) { | 1375 } else if (type.isBottom) { |
1388 return js.call('dart.bottom'); | 1376 return js.call('dart.bottom'); |
1389 } | 1377 } |
1390 | 1378 |
1391 _loader.declareBeforeUse(type.element); | 1379 _loader.declareBeforeUse(type.element); |
1392 | 1380 |
1393 // TODO(jmesserly): like constants, should we hoist function types out of | 1381 // TODO(jmesserly): like constants, should we hoist function types out of |
1394 // methods? Similar issue with generic types. For all of these, we may want | 1382 // methods? Similar issue with generic types. For all of these, we may want |
1395 // to canonicalize them too, at least when inside the same library. | 1383 // to canonicalize them too, at least when inside the same library. |
1396 var name = type.name; | 1384 var name = type.name; |
(...skipping 1405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2802 | 2790 |
2803 /// A special kind of element created by the compiler, signifying a temporary | 2791 /// A special kind of element created by the compiler, signifying a temporary |
2804 /// variable. These objects use instance equality, and should be shared | 2792 /// variable. These objects use instance equality, and should be shared |
2805 /// everywhere in the tree where they are treated as the same variable. | 2793 /// everywhere in the tree where they are treated as the same variable. |
2806 class TemporaryVariableElement extends LocalVariableElementImpl { | 2794 class TemporaryVariableElement extends LocalVariableElementImpl { |
2807 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); | 2795 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); |
2808 | 2796 |
2809 int get hashCode => identityHashCode(this); | 2797 int get hashCode => identityHashCode(this); |
2810 bool operator ==(Object other) => identical(this, other); | 2798 bool operator ==(Object other) => identical(this, other); |
2811 } | 2799 } |
OLD | NEW |