Chromium Code Reviews| 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 | |
| 456 var jsFrom = _visit(fromExpr); | |
| 457 var from = getStaticType(fromExpr); | |
| 458 | |
| 459 JS.Expression maybeCheckNull(JS.Expression jsExpr) { | |
|
Jennifer Messerly
2016/05/10 23:42:12
aside: it might be a better architecture to fuse t
| |
| 460 if (checkNull && isNullable(fromExpr)) { | |
| 461 return js.call('dart.notNull(#)', jsExpr); | |
| 462 } | |
| 463 return jsExpr; | |
| 464 } | |
| 454 | 465 |
| 455 // Skip the cast if it's not needed. | 466 // Skip the cast if it's not needed. |
| 456 if (rules.isSubtypeOf(from, to)) return fromExpr; | 467 if (to == null || rules.isSubtypeOf(from, to)) { |
| 468 return maybeCheckNull(jsFrom); | |
| 469 } | |
| 457 | 470 |
| 458 // All Dart number types map to a JS double. | 471 // All Dart number types map to a JS double. |
| 459 if (_isNumberInJS(from) && _isNumberInJS(to)) { | 472 if (_isNumberInJS(from) && _isNumberInJS(to)) { |
| 460 // Make sure to check when converting to int. | 473 // Make sure to check when converting to int. |
| 461 if (from != types.intType && to == types.intType) { | 474 if (from != types.intType && to == types.intType) { |
| 462 return js.call('dart.asInt(#)', [fromExpr]); | 475 // TODO(jmesserly): fuse this with notNull check. |
| 476 return maybeCheckNull(js.call('dart.asInt(#)', [jsFrom])); | |
| 463 } | 477 } |
| 464 | 478 |
| 465 // A no-op in JavaScript. | 479 // A no-op in JavaScript. |
| 466 return fromExpr; | 480 return maybeCheckNull(jsFrom); |
| 467 } | 481 } |
| 468 | 482 |
| 469 return js.call('dart.as(#, #)', [fromExpr, _emitType(to)]); | 483 if (to == types.boolType && checkNull) { |
| 484 return js.call('dart.test(#)', _visit(fromExpr)); | |
| 485 } | |
| 486 | |
| 487 if (checkNull && isNullable(fromExpr)) { | |
| 488 return js.call('dart.asNotNull(#, #)', [jsFrom, _emitType(to)]); | |
| 489 } else { | |
| 490 return js.call('dart.as(#, #)', [jsFrom, _emitType(to)]); | |
| 491 } | |
| 470 } | 492 } |
| 471 | 493 |
| 472 @override | 494 @override |
| 473 visitIsExpression(IsExpression node) { | 495 visitIsExpression(IsExpression node) { |
| 474 // Generate `is` as `dart.is` or `typeof` depending on the RHS type. | 496 // Generate `is` as `dart.is` or `typeof` depending on the RHS type. |
| 475 JS.Expression result; | 497 JS.Expression result; |
| 476 var type = node.type.type; | 498 var type = node.type.type; |
| 477 var lhs = _visit(node.expression); | 499 var lhs = _visit(node.expression); |
| 478 var typeofName = _jsTypeofName(type); | 500 var typeofName = _jsTypeofName(type); |
| 479 if (typeofName != null) { | 501 if (typeofName != null) { |
| (...skipping 2572 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3052 bool typeIsPrimitiveInJS(DartType t) => | 3074 bool typeIsPrimitiveInJS(DartType t) => |
| 3053 _isNumberInJS(t) || t == types.boolType; | 3075 _isNumberInJS(t) || t == types.boolType; |
| 3054 | 3076 |
| 3055 bool binaryOperationIsPrimitive(DartType leftT, DartType rightT) => | 3077 bool binaryOperationIsPrimitive(DartType leftT, DartType rightT) => |
| 3056 typeIsPrimitiveInJS(leftT) && typeIsPrimitiveInJS(rightT); | 3078 typeIsPrimitiveInJS(leftT) && typeIsPrimitiveInJS(rightT); |
| 3057 | 3079 |
| 3058 bool unaryOperationIsPrimitive(DartType t) => typeIsPrimitiveInJS(t); | 3080 bool unaryOperationIsPrimitive(DartType t) => typeIsPrimitiveInJS(t); |
| 3059 | 3081 |
| 3060 JS.Expression notNull(Expression expr) { | 3082 JS.Expression notNull(Expression expr) { |
| 3061 if (expr == null) return null; | 3083 if (expr == null) return null; |
| 3062 var jsExpr = _visit(expr); | 3084 if (expr is AsExpression) { |
| 3063 if (!isNullable(expr)) return jsExpr; | 3085 return _emitCast(expr.expression, to: expr.type.type, checkNull: true); |
| 3064 return js.call('dart.notNull(#)', jsExpr); | 3086 } |
| 3087 return _emitCast(expr, checkNull: true); | |
| 3065 } | 3088 } |
| 3066 | 3089 |
| 3067 @override | 3090 @override |
| 3068 JS.Expression visitBinaryExpression(BinaryExpression node) { | 3091 JS.Expression visitBinaryExpression(BinaryExpression node) { |
| 3069 var op = node.operator; | 3092 var op = node.operator; |
| 3070 var left = node.leftOperand; | 3093 var left = node.leftOperand; |
| 3071 var right = node.rightOperand; | 3094 var right = node.rightOperand; |
| 3072 | 3095 |
| 3073 var leftType = getStaticType(left); | 3096 var leftType = getStaticType(left); |
| 3074 var rightType = getStaticType(right); | 3097 var rightType = getStaticType(right); |
| (...skipping 1333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4408 } | 4431 } |
| 4409 | 4432 |
| 4410 bool isLibraryPrefix(Expression node) => | 4433 bool isLibraryPrefix(Expression node) => |
| 4411 node is SimpleIdentifier && node.staticElement is PrefixElement; | 4434 node is SimpleIdentifier && node.staticElement is PrefixElement; |
| 4412 | 4435 |
| 4413 LibraryElement _getLibrary(AnalysisContext c, String uri) => | 4436 LibraryElement _getLibrary(AnalysisContext c, String uri) => |
| 4414 c.computeLibraryElement(c.sourceFactory.forUri(uri)); | 4437 c.computeLibraryElement(c.sourceFactory.forUri(uri)); |
| 4415 | 4438 |
| 4416 bool _isDartRuntime(LibraryElement l) => | 4439 bool _isDartRuntime(LibraryElement l) => |
| 4417 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; | 4440 l.isInSdk && l.source.uri.toString() == 'dart:_runtime'; |
| OLD | NEW |