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

Side by Side Diff: lib/src/codegen/js_codegen.dart

Issue 1348453004: fix some errors in our SDK, mostly around numbers (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: format Created 5 years, 3 months 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 // 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 293 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 return 'Symbol'; 304 return 'Symbol';
305 } 305 }
306 306
307 bool isPublic(String name) => !name.startsWith('_'); 307 bool isPublic(String name) => !name.startsWith('_');
308 308
309 @override 309 @override
310 visitAsExpression(AsExpression node) { 310 visitAsExpression(AsExpression node) {
311 var from = getStaticType(node.expression); 311 var from = getStaticType(node.expression);
312 var to = node.type.type; 312 var to = node.type.type;
313 313
314 var fromExpr = _visit(node.expression);
315
314 // Skip the cast if it's not needed. 316 // Skip the cast if it's not needed.
315 if (rules.isSubTypeOf(from, to)) return _visit(node.expression); 317 if (rules.isSubTypeOf(from, to)) return fromExpr;
316 318
317 // All Dart number types map to a JS double. 319 // All Dart number types map to a JS double.
318 if (rules.isNumType(from) && 320 if (rules.isNumberInJS(from) && rules.isNumberInJS(to)) {
319 (rules.isIntType(to) || rules.isDoubleType(to))) { 321 // TODO(jmesserly): explicit check from num to int or double to int?
Leaf 2015/09/18 22:37:49 I think this changes the semantics a little, since
Jennifer Messerly 2015/09/18 22:42:27 I think previously double -> int was a cast. Howev
Jennifer Messerly 2015/09/18 22:44:36 so from a type system perspective, if JSNumber can
Leaf 2015/09/18 22:57:48 I'm not hard set on this, but I'm just a little wo
320 // TODO(jmesserly): a lot of these checks are meaningless, as people use 322
321 // `num` to mean "any kind of number" rather than "could be null".
322 // The core libraries especially suffer from this problem, with many of
323 // the `num` methods returning `num`.
324 if (!rules.isNonNullableType(from) && rules.isNonNullableType(to)) { 323 if (!rules.isNonNullableType(from) && rules.isNonNullableType(to)) {
325 // Converting from a nullable number to a non-nullable number 324 // Converting from a nullable number to a non-nullable number
326 // only requires a null check. 325 // only requires a null check.
327 return js.call('dart.notNull(#)', _visit(node.expression)); 326 // TODO(jmesserly): a lot of these checks are meaningless, as people use
327 // `num` to mean "any kind of number" rather than "could be null".
328 // The core libraries especially suffer from this problem, with many of
329 // the `num` methods returning `num`.
330 return js.call('dart.notNull(#)', fromExpr);
328 } else { 331 } else {
329 // A no-op in JavaScript. 332 // A no-op in JavaScript.
330 return _visit(node.expression); 333 return fromExpr;
331 } 334 }
332 } 335 }
333 336
334 return _emitCast(node.expression, to); 337 return js.call('dart.as(#, #)', [fromExpr, _emitTypeName(to)]);
335 } 338 }
336 339
337 _emitCast(Expression node, DartType type) => js.call('dart.as(#)', [
338 [_visit(node), _emitTypeName(type)]
339 ]);
340
341 @override 340 @override
342 visitIsExpression(IsExpression node) { 341 visitIsExpression(IsExpression node) {
343 // Generate `is` as `dart.is` or `typeof` depending on the RHS type. 342 // Generate `is` as `dart.is` or `typeof` depending on the RHS type.
344 JS.Expression result; 343 JS.Expression result;
345 var type = node.type.type; 344 var type = node.type.type;
346 var lhs = _visit(node.expression); 345 var lhs = _visit(node.expression);
347 var typeofName = _jsTypeofName(type); 346 var typeofName = _jsTypeofName(type);
348 if (typeofName != null) { 347 if (typeofName != null) {
349 result = js.call('typeof # == #', [lhs, js.string(typeofName, "'")]); 348 result = js.call('typeof # == #', [lhs, js.string(typeofName, "'")]);
350 } else { 349 } else {
351 // Always go through a runtime helper, because implicit interfaces. 350 // Always go through a runtime helper, because implicit interfaces.
352 result = js.call('dart.is(#, #)', [lhs, _emitTypeName(type)]); 351 result = js.call('dart.is(#, #)', [lhs, _emitTypeName(type)]);
353 } 352 }
354 353
355 if (node.notOperator != null) { 354 if (node.notOperator != null) {
356 return js.call('!#', result); 355 return js.call('!#', result);
357 } 356 }
358 return result; 357 return result;
359 } 358 }
360 359
361 String _jsTypeofName(DartType t) { 360 String _jsTypeofName(DartType t) {
362 if (rules.isIntType(t) || rules.isDoubleType(t)) return 'number'; 361 if (rules.isNumberInJS(t)) return 'number';
363 if (rules.isStringType(t)) return 'string'; 362 if (rules.isStringType(t)) return 'string';
364 if (rules.isBoolType(t)) return 'boolean'; 363 if (rules.isBoolType(t)) return 'boolean';
365 return null; 364 return null;
366 } 365 }
367 366
368 @override 367 @override
369 visitFunctionTypeAlias(FunctionTypeAlias node) { 368 visitFunctionTypeAlias(FunctionTypeAlias node) {
370 var element = node.element; 369 var element = node.element;
371 var type = element.type; 370 var type = element.type;
372 var name = element.name; 371 var name = element.name;
(...skipping 1786 matching lines...) Expand 10 before | Expand all | Expand 10 after
2159 element, type, name, node.argumentList, node.isConst); 2158 element, type, name, node.argumentList, node.isConst);
2160 } 2159 }
2161 2160
2162 /// True if this type is built-in to JS, and we use the values unwrapped. 2161 /// True if this type is built-in to JS, and we use the values unwrapped.
2163 /// For these types we generate a calling convention via static 2162 /// For these types we generate a calling convention via static
2164 /// "extension methods". This allows types to be extended without adding 2163 /// "extension methods". This allows types to be extended without adding
2165 /// extensions directly on the prototype. 2164 /// extensions directly on the prototype.
2166 bool _isJSBuiltinType(DartType t) => 2165 bool _isJSBuiltinType(DartType t) =>
2167 typeIsPrimitiveInJS(t) || rules.isStringType(t); 2166 typeIsPrimitiveInJS(t) || rules.isStringType(t);
2168 2167
2169 bool typeIsPrimitiveInJS(DartType t) => rules.isIntType(t) || 2168 bool typeIsPrimitiveInJS(DartType t) =>
2170 rules.isDoubleType(t) || 2169 rules.isNumberInJS(t) || rules.isBoolType(t);
2171 rules.isBoolType(t) ||
2172 rules.isNumType(t);
2173 2170
2174 bool typeIsNonNullablePrimitiveInJS(DartType t) => 2171 bool typeIsNonNullablePrimitiveInJS(DartType t) =>
2175 typeIsPrimitiveInJS(t) && rules.isNonNullableType(t); 2172 typeIsPrimitiveInJS(t) && rules.isNonNullableType(t);
2176 2173
2177 bool binaryOperationIsPrimitive(DartType leftT, DartType rightT) => 2174 bool binaryOperationIsPrimitive(DartType leftT, DartType rightT) =>
2178 typeIsPrimitiveInJS(leftT) && typeIsPrimitiveInJS(rightT); 2175 typeIsPrimitiveInJS(leftT) && typeIsPrimitiveInJS(rightT);
2179 2176
2180 bool unaryOperationIsPrimitive(DartType t) => typeIsPrimitiveInJS(t); 2177 bool unaryOperationIsPrimitive(DartType t) => typeIsPrimitiveInJS(t);
2181 2178
2182 bool _isNonNullableExpression(Expression expr) { 2179 bool _isNonNullableExpression(Expression expr) {
(...skipping 1073 matching lines...) Expand 10 before | Expand all | Expand 10 after
3256 class JSGenerator extends CodeGenerator { 3253 class JSGenerator extends CodeGenerator {
3257 final _extensionTypes = new HashSet<ClassElement>(); 3254 final _extensionTypes = new HashSet<ClassElement>();
3258 3255
3259 JSGenerator(AbstractCompiler compiler) : super(compiler) { 3256 JSGenerator(AbstractCompiler compiler) : super(compiler) {
3260 // TODO(jacobr): determine the the set of types with extension methods from 3257 // TODO(jacobr): determine the the set of types with extension methods from
3261 // the annotations rather than hard coding the list once the analyzer 3258 // the annotations rather than hard coding the list once the analyzer
3262 // supports summaries. 3259 // supports summaries.
3263 var context = compiler.context; 3260 var context = compiler.context;
3264 var src = context.sourceFactory.forUri('dart:_interceptors'); 3261 var src = context.sourceFactory.forUri('dart:_interceptors');
3265 var interceptors = context.computeLibraryElement(src); 3262 var interceptors = context.computeLibraryElement(src);
3266 for (var t in ['JSArray', 'JSString', 'JSInt', 'JSDouble', 'JSBool']) { 3263 for (var t in ['JSArray', 'JSString', 'JSNumber', 'JSBool']) {
3267 _addExtensionType(interceptors.getType(t).type); 3264 _addExtensionType(interceptors.getType(t).type);
3268 } 3265 }
3266 // TODO(jmesserly): manually add `int` and `double`
3267 // Unfortunately our current analyzer rejects "implements int".
3268 // Fix was landed, so we can remove this hack once we're updated:
3269 // https://github.com/dart-lang/sdk/commit/d7cd11f86a02f55269fc8d9843e7758eb eeb81c8
3270 _addExtensionType(context.typeProvider.intType);
3271 _addExtensionType(context.typeProvider.doubleType);
3269 } 3272 }
3270 3273
3271 void _addExtensionType(InterfaceType t) { 3274 void _addExtensionType(InterfaceType t) {
3272 if (t.isObject || !_extensionTypes.add(t.element)) return; 3275 if (t.isObject || !_extensionTypes.add(t.element)) return;
3273 t = fillDynamicTypeArgs(t, rules.provider) as InterfaceType; 3276 t = fillDynamicTypeArgs(t, rules.provider) as InterfaceType;
3274 t.interfaces.forEach(_addExtensionType); 3277 t.interfaces.forEach(_addExtensionType);
3275 t.mixins.forEach(_addExtensionType); 3278 t.mixins.forEach(_addExtensionType);
3276 _addExtensionType(t.superclass); 3279 _addExtensionType(t.superclass);
3277 } 3280 }
3278 3281
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
3315 3318
3316 /// A special kind of element created by the compiler, signifying a temporary 3319 /// A special kind of element created by the compiler, signifying a temporary
3317 /// variable. These objects use instance equality, and should be shared 3320 /// variable. These objects use instance equality, and should be shared
3318 /// everywhere in the tree where they are treated as the same variable. 3321 /// everywhere in the tree where they are treated as the same variable.
3319 class TemporaryVariableElement extends LocalVariableElementImpl { 3322 class TemporaryVariableElement extends LocalVariableElementImpl {
3320 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); 3323 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name);
3321 3324
3322 int get hashCode => identityHashCode(this); 3325 int get hashCode => identityHashCode(this);
3323 bool operator ==(Object other) => identical(this, other); 3326 bool operator ==(Object other) => identical(this, other);
3324 } 3327 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698