| 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 |