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 import 'dart:collection' show HashMap, HashSet; | 5 import 'dart:collection' show HashMap, HashSet; |
6 import 'dart:math' show min, max; | 6 import 'dart:math' show min, max; |
7 | 7 |
8 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 8 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; |
10 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType; | 10 import 'package:analyzer/dart/ast/token.dart' show Token, TokenType; |
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
439 if (export is ClassElement && export.typeParameters.isNotEmpty) { | 439 if (export is ClassElement && export.typeParameters.isNotEmpty) { |
440 // Export the generic name as well. | 440 // Export the generic name as well. |
441 // TODO(jmesserly): revisit generic classes | 441 // TODO(jmesserly): revisit generic classes |
442 emitExport(export, suffix: r'$'); | 442 emitExport(export, suffix: r'$'); |
443 } | 443 } |
444 emitExport(export); | 444 emitExport(export); |
445 } | 445 } |
446 } | 446 } |
447 | 447 |
448 @override | 448 @override |
449 visitAsExpression(AsExpression node) { | 449 visitAsExpression(AsExpression node) => |
450 var from = getStaticType(node.expression); | 450 _emitCast(node.expression, to: node.type.type); |
451 var to = node.type.type; | |
452 | 451 |
453 var fromExpr = _visit(node.expression); | 452 /// Emits a cast and/or a null check (i.e. a cast to a non-null type). |
| 453 JS.Expression _emitCast(Expression fromExpr, |
| 454 {DartType to, bool checkNull: false}) { |
| 455 var jsFrom = _visit(fromExpr); |
| 456 var from = getStaticType(fromExpr); |
| 457 |
| 458 JS.Expression maybeCheckNull(JS.Expression jsExpr) { |
| 459 if (checkNull && isNullable(fromExpr)) { |
| 460 return js.call('dart.notNull(#)', jsExpr); |
| 461 } |
| 462 return jsExpr; |
| 463 } |
454 | 464 |
455 // Skip the cast if it's not needed. | 465 // Skip the cast if it's not needed. |
456 if (rules.isSubtypeOf(from, to)) return fromExpr; | 466 if (to == null || rules.isSubtypeOf(from, to)) { |
| 467 return maybeCheckNull(jsFrom); |
| 468 } |
457 | 469 |
458 // All Dart number types map to a JS double. | 470 // All Dart number types map to a JS double. |
459 if (_isNumberInJS(from) && _isNumberInJS(to)) { | 471 if (_isNumberInJS(from) && _isNumberInJS(to)) { |
460 // Make sure to check when converting to int. | 472 // Make sure to check when converting to int. |
461 if (from != types.intType && to == types.intType) { | 473 if (from != types.intType && to == types.intType) { |
462 return js.call('dart.asInt(#)', [fromExpr]); | 474 // TODO(jmesserly): fuse this with notNull check. |
| 475 return maybeCheckNull(js.call('dart.asInt(#)', [jsFrom])); |
463 } | 476 } |
464 | 477 |
465 // A no-op in JavaScript. | 478 // A no-op in JavaScript. |
466 return fromExpr; | 479 return maybeCheckNull(jsFrom); |
467 } | 480 } |
468 | 481 |
469 return js.call('dart.as(#, #)', [fromExpr, _emitType(to)]); | 482 if (to == types.boolType && checkNull) { |
| 483 return js.call('dart.test(#)', _visit(fromExpr)); |
| 484 } |
| 485 |
| 486 return maybeCheckNull(js.call('dart.as(#, #)', [jsFrom, _emitType(to)])); |
470 } | 487 } |
471 | 488 |
472 @override | 489 @override |
473 visitIsExpression(IsExpression node) { | 490 visitIsExpression(IsExpression node) { |
474 // Generate `is` as `dart.is` or `typeof` depending on the RHS type. | 491 // Generate `is` as `dart.is` or `typeof` depending on the RHS type. |
475 JS.Expression result; | 492 JS.Expression result; |
476 var type = node.type.type; | 493 var type = node.type.type; |
477 var lhs = _visit(node.expression); | 494 var lhs = _visit(node.expression); |
478 var typeofName = _jsTypeofName(type); | 495 var typeofName = _jsTypeofName(type); |
479 if (typeofName != null) { | 496 if (typeofName != null) { |
(...skipping 2572 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3052 bool typeIsPrimitiveInJS(DartType t) => | 3069 bool typeIsPrimitiveInJS(DartType t) => |
3053 _isNumberInJS(t) || t == types.boolType; | 3070 _isNumberInJS(t) || t == types.boolType; |
3054 | 3071 |
3055 bool binaryOperationIsPrimitive(DartType leftT, DartType rightT) => | 3072 bool binaryOperationIsPrimitive(DartType leftT, DartType rightT) => |
3056 typeIsPrimitiveInJS(leftT) && typeIsPrimitiveInJS(rightT); | 3073 typeIsPrimitiveInJS(leftT) && typeIsPrimitiveInJS(rightT); |
3057 | 3074 |
3058 bool unaryOperationIsPrimitive(DartType t) => typeIsPrimitiveInJS(t); | 3075 bool unaryOperationIsPrimitive(DartType t) => typeIsPrimitiveInJS(t); |
3059 | 3076 |
3060 JS.Expression notNull(Expression expr) { | 3077 JS.Expression notNull(Expression expr) { |
3061 if (expr == null) return null; | 3078 if (expr == null) return null; |
3062 var jsExpr = _visit(expr); | 3079 if (expr is AsExpression) { |
3063 if (!isNullable(expr)) return jsExpr; | 3080 return _emitCast(expr.expression, to: expr.type.type, checkNull: true); |
3064 return js.call('dart.notNull(#)', jsExpr); | 3081 } |
| 3082 return _emitCast(expr, checkNull: true); |
3065 } | 3083 } |
3066 | 3084 |
3067 @override | 3085 @override |
3068 JS.Expression visitBinaryExpression(BinaryExpression node) { | 3086 JS.Expression visitBinaryExpression(BinaryExpression node) { |
3069 var op = node.operator; | 3087 var op = node.operator; |
3070 var left = node.leftOperand; | 3088 var left = node.leftOperand; |
3071 var right = node.rightOperand; | 3089 var right = node.rightOperand; |
3072 | 3090 |
3073 var leftType = getStaticType(left); | 3091 var leftType = getStaticType(left); |
3074 var rightType = getStaticType(right); | 3092 var rightType = getStaticType(right); |
(...skipping 1333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4408 } | 4426 } |
4409 | 4427 |
4410 bool isLibraryPrefix(Expression node) => | 4428 bool isLibraryPrefix(Expression node) => |
4411 node is SimpleIdentifier && node.staticElement is PrefixElement; | 4429 node is SimpleIdentifier && node.staticElement is PrefixElement; |
4412 | 4430 |
4413 LibraryElement _getLibrary(AnalysisContext c, String uri) => | 4431 LibraryElement _getLibrary(AnalysisContext c, String uri) => |
4414 c.computeLibraryElement(c.sourceFactory.forUri(uri)); | 4432 c.computeLibraryElement(c.sourceFactory.forUri(uri)); |
4415 | 4433 |
4416 bool _isDartRuntime(LibraryElement l) => | 4434 bool _isDartRuntime(LibraryElement l) => |
4417 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; | 4435 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; |
OLD | NEW |