| 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; | 7 import 'dart:collection' show HashSet, HashMap; |
| 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 581 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 592 if (!(node.isSetter || node.isGetter || node.isAbstract)) { | 592 if (!(node.isSetter || node.isGetter || node.isAbstract)) { |
| 593 var name = node.name.name; | 593 var name = node.name.name; |
| 594 var element = node.element; | 594 var element = node.element; |
| 595 var inheritedElement = | 595 var inheritedElement = |
| 596 classElem.lookUpInheritedConcreteMethod(name, currentLibrary); | 596 classElem.lookUpInheritedConcreteMethod(name, currentLibrary); |
| 597 if (inheritedElement != null && | 597 if (inheritedElement != null && |
| 598 inheritedElement.type == element.type) continue; | 598 inheritedElement.type == element.type) continue; |
| 599 var unary = node.parameters.parameters.isEmpty; | 599 var unary = node.parameters.parameters.isEmpty; |
| 600 var memberName = _emitMemberName(name, | 600 var memberName = _emitMemberName(name, |
| 601 type: cType, unary: unary, isStatic: node.isStatic); | 601 type: cType, unary: unary, isStatic: node.isStatic); |
| 602 var parts = _emitFunctionTypeParts(element.type); | 602 var parts = |
| 603 _emitFunctionTypeParts(element.type, dynamicIsBottom: false); |
| 603 var property = | 604 var property = |
| 604 new JS.Property(memberName, new JS.ArrayInitializer(parts)); | 605 new JS.Property(memberName, new JS.ArrayInitializer(parts)); |
| 605 if (node.isStatic) { | 606 if (node.isStatic) { |
| 606 tStatics.add(property); | 607 tStatics.add(property); |
| 607 sNames.add(memberName); | 608 sNames.add(memberName); |
| 608 } else tMethods.add(property); | 609 } else tMethods.add(property); |
| 609 } | 610 } |
| 610 } | 611 } |
| 611 build(name, elements) { | 612 build(name, elements) { |
| 612 var o = | 613 var o = |
| 613 new JS.ObjectInitializer(elements, vertical: elements.length > 1); | 614 new JS.ObjectInitializer(elements, vertical: elements.length > 1); |
| 614 var e = js.call('() => #', o); | 615 var e = js.call('() => #', o); |
| 615 var p = new JS.Property(_propertyName(name), e); | 616 var p = new JS.Property(_propertyName(name), e); |
| (...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1019 var lazy = topLevel && !_typeIsLoaded(type); | 1020 var lazy = topLevel && !_typeIsLoaded(type); |
| 1020 | 1021 |
| 1021 if (type is FunctionType && (name == '' || name == null)) { | 1022 if (type is FunctionType && (name == '' || name == null)) { |
| 1022 if (type.returnType.isDynamic && | 1023 if (type.returnType.isDynamic && |
| 1023 type.optionalParameterTypes.isEmpty && | 1024 type.optionalParameterTypes.isEmpty && |
| 1024 type.namedParameterTypes.isEmpty && | 1025 type.namedParameterTypes.isEmpty && |
| 1025 type.normalParameterTypes.every((t) => t.isDynamic)) { | 1026 type.normalParameterTypes.every((t) => t.isDynamic)) { |
| 1026 return js.call('dart.fn(#)', [clos]); | 1027 return js.call('dart.fn(#)', [clos]); |
| 1027 } | 1028 } |
| 1028 if (lazy) { | 1029 if (lazy) { |
| 1029 return js.call('dart.fn(#, () => #)', [clos, _emitTypeName(type)]); | 1030 return js.call('dart.fn(#, () => #)', [clos, _emitFunctionRTTI(type)]); |
| 1030 } | 1031 } |
| 1031 return js.call('dart.fn(#, #)', [clos, _emitFunctionTypeParts(type)]); | 1032 return js.call('dart.fn(#, #)', [ |
| 1033 clos, |
| 1034 _emitFunctionTypeParts(type, dynamicIsBottom: false) |
| 1035 ]); |
| 1032 } | 1036 } |
| 1033 throw 'Function has non function type: $type'; | 1037 throw 'Function has non function type: $type'; |
| 1034 } | 1038 } |
| 1035 | 1039 |
| 1036 @override | 1040 @override |
| 1037 JS.Expression visitFunctionExpression(FunctionExpression node) { | 1041 JS.Expression visitFunctionExpression(FunctionExpression node) { |
| 1038 var params = _visit(node.parameters); | 1042 var params = _visit(node.parameters); |
| 1039 if (params == null) params = []; | 1043 if (params == null) params = []; |
| 1040 | 1044 |
| 1041 var parent = node.parent; | 1045 var parent = node.parent; |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1153 return _getTemp(element, name); | 1157 return _getTemp(element, name); |
| 1154 } | 1158 } |
| 1155 } | 1159 } |
| 1156 | 1160 |
| 1157 return new JS.Identifier(name); | 1161 return new JS.Identifier(name); |
| 1158 } | 1162 } |
| 1159 | 1163 |
| 1160 JS.TemporaryId _getTemp(Object key, String name) => | 1164 JS.TemporaryId _getTemp(Object key, String name) => |
| 1161 _temps.putIfAbsent(key, () => new JS.TemporaryId(name)); | 1165 _temps.putIfAbsent(key, () => new JS.TemporaryId(name)); |
| 1162 | 1166 |
| 1163 JS.ArrayInitializer _emitTypeNames(List<DartType> types) { | 1167 JS.ArrayInitializer _emitTypeNames(List<DartType> types, |
| 1164 return new JS.ArrayInitializer(types.map(_emitTypeName).toList()); | 1168 {dynamicIsBottom: false}) { |
| 1169 var build = (t) => _emitTypeName(t, dynamicIsBottom: dynamicIsBottom); |
| 1170 return new JS.ArrayInitializer(types.map(build).toList()); |
| 1165 } | 1171 } |
| 1166 | 1172 |
| 1167 JS.ObjectInitializer _emitTypeProperties(Map<String, DartType> types) { | 1173 JS.ObjectInitializer _emitTypeProperties(Map<String, DartType> types, |
| 1174 {dynamicIsBottom: false}) { |
| 1168 var properties = <JS.Property>[]; | 1175 var properties = <JS.Property>[]; |
| 1169 types.forEach((name, type) { | 1176 types.forEach((name, type) { |
| 1170 var key = new JS.LiteralString(name); | 1177 var key = new JS.LiteralString(name); |
| 1171 var value = _emitTypeName(type); | 1178 var value = _emitTypeName(type, dynamicIsBottom: dynamicIsBottom); |
| 1172 properties.add(new JS.Property(key, value)); | 1179 properties.add(new JS.Property(key, value)); |
| 1173 }); | 1180 }); |
| 1174 return new JS.ObjectInitializer(properties); | 1181 return new JS.ObjectInitializer(properties); |
| 1175 } | 1182 } |
| 1176 | 1183 |
| 1177 List<JS.Expression> _emitFunctionTypeParts(FunctionType type) { | 1184 /// Emit the pieces of a function type, as an array of return type, |
| 1185 /// regular args, and optional/named args. |
| 1186 /// If [dynamicIsBottom] is true, then dynamics in argument positions |
| 1187 /// will be lowered to bottom instead of Object. |
| 1188 List<JS.Expression> _emitFunctionTypeParts(FunctionType type, |
| 1189 {bool dynamicIsBottom: true}) { |
| 1178 var returnType = type.returnType; | 1190 var returnType = type.returnType; |
| 1179 var parameterTypes = type.normalParameterTypes; | 1191 var parameterTypes = type.normalParameterTypes; |
| 1180 var optionalTypes = type.optionalParameterTypes; | 1192 var optionalTypes = type.optionalParameterTypes; |
| 1181 var namedTypes = type.namedParameterTypes; | 1193 var namedTypes = type.namedParameterTypes; |
| 1182 var rt = _emitTypeName(returnType); | 1194 var rt = _emitTypeName(returnType); |
| 1183 var ra = _emitTypeNames(parameterTypes); | 1195 var ra = _emitTypeNames(parameterTypes, dynamicIsBottom: dynamicIsBottom); |
| 1184 if (!namedTypes.isEmpty) { | 1196 if (!namedTypes.isEmpty) { |
| 1185 assert(optionalTypes.isEmpty); | 1197 assert(optionalTypes.isEmpty); |
| 1186 var na = _emitTypeProperties(namedTypes); | 1198 var na = |
| 1199 _emitTypeProperties(namedTypes, dynamicIsBottom: dynamicIsBottom); |
| 1187 return [rt, ra, na]; | 1200 return [rt, ra, na]; |
| 1188 } | 1201 } |
| 1189 if (!optionalTypes.isEmpty) { | 1202 if (!optionalTypes.isEmpty) { |
| 1190 assert(namedTypes.isEmpty); | 1203 assert(namedTypes.isEmpty); |
| 1191 var oa = _emitTypeNames(optionalTypes); | 1204 var oa = _emitTypeNames(optionalTypes, dynamicIsBottom: dynamicIsBottom); |
| 1192 return [rt, ra, oa]; | 1205 return [rt, ra, oa]; |
| 1193 } | 1206 } |
| 1194 return [rt, ra]; | 1207 return [rt, ra]; |
| 1195 } | 1208 } |
| 1196 | 1209 |
| 1210 JS.Expression _emitFunctionRTTI(FunctionType type) { |
| 1211 var parts = _emitFunctionTypeParts(type, dynamicIsBottom: false); |
| 1212 return js.call('dart.functionType(#)', [parts]); |
| 1213 } |
| 1214 |
| 1197 /// Emits a Dart [type] into code. | 1215 /// Emits a Dart [type] into code. |
| 1198 /// | 1216 /// |
| 1199 /// If [lowerTypedef] is set, a typedef will be expanded as if it were a | 1217 /// If [lowerTypedef] is set, a typedef will be expanded as if it were a |
| 1200 /// function type. Similarly if [lowerGeneric] is set, the `List$()` form | 1218 /// function type. Similarly if [lowerGeneric] is set, the `List$()` form |
| 1201 /// will be used instead of `List`. These flags are used when generating | 1219 /// will be used instead of `List`. These flags are used when generating |
| 1202 /// the definitions for typedefs and generic types, respectively. | 1220 /// the definitions for typedefs and generic types, respectively. |
| 1203 JS.Expression _emitTypeName(DartType type, | 1221 JS.Expression _emitTypeName(DartType type, {bool lowerTypedef: false, |
| 1204 {bool lowerTypedef: false, bool lowerGeneric: false}) { | 1222 bool lowerGeneric: false, bool dynamicIsBottom: false}) { |
| 1205 | 1223 |
| 1206 // The void and dynamic types are not defined in core. | 1224 // The void and dynamic types are not defined in core. |
| 1207 if (type.isVoid) { | 1225 if (type.isVoid) { |
| 1208 return js.call('dart.void'); | 1226 return js.call('dart.void'); |
| 1209 } else if (type.isDynamic) { | 1227 } else if (type.isDynamic) { |
| 1210 return js.call('dart.dynamic'); | 1228 if (dynamicIsBottom) return js.call('dart.bottom'); |
| 1229 return _emitTypeName(types.objectType); |
| 1211 } else if (type.isBottom) { | 1230 } else if (type.isBottom) { |
| 1212 return js.call('dart.bottom'); | 1231 return js.call('dart.bottom'); |
| 1213 } | 1232 } |
| 1214 | 1233 |
| 1215 _loader.declareBeforeUse(type.element); | 1234 _loader.declareBeforeUse(type.element); |
| 1216 | 1235 |
| 1217 // TODO(jmesserly): like constants, should we hoist function types out of | 1236 // TODO(jmesserly): like constants, should we hoist function types out of |
| 1218 // methods? Similar issue with generic types. For all of these, we may want | 1237 // methods? Similar issue with generic types. For all of these, we may want |
| 1219 // to canonicalize them too, at least when inside the same library. | 1238 // to canonicalize them too, at least when inside the same library. |
| 1220 var name = type.name; | 1239 var name = type.name; |
| (...skipping 1362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2583 | 2602 |
| 2584 /// A special kind of element created by the compiler, signifying a temporary | 2603 /// A special kind of element created by the compiler, signifying a temporary |
| 2585 /// variable. These objects use instance equality, and should be shared | 2604 /// variable. These objects use instance equality, and should be shared |
| 2586 /// everywhere in the tree where they are treated as the same variable. | 2605 /// everywhere in the tree where they are treated as the same variable. |
| 2587 class TemporaryVariableElement extends LocalVariableElementImpl { | 2606 class TemporaryVariableElement extends LocalVariableElementImpl { |
| 2588 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); | 2607 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); |
| 2589 | 2608 |
| 2590 int get hashCode => identityHashCode(this); | 2609 int get hashCode => identityHashCode(this); |
| 2591 bool operator ==(Object other) => identical(this, other); | 2610 bool operator ==(Object other) => identical(this, other); |
| 2592 } | 2611 } |
| OLD | NEW |