| 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 import 'dart:io' show Directory, File; | 8 import 'dart:io' show Directory, File; |
| 9 | 9 |
| 10 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 10 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
| (...skipping 1429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1440 JS.Expression visitBinaryExpression(BinaryExpression node) { | 1440 JS.Expression visitBinaryExpression(BinaryExpression node) { |
| 1441 var op = node.operator; | 1441 var op = node.operator; |
| 1442 var left = node.leftOperand; | 1442 var left = node.leftOperand; |
| 1443 var right = node.rightOperand; | 1443 var right = node.rightOperand; |
| 1444 var leftType = rules.getStaticType(left); | 1444 var leftType = rules.getStaticType(left); |
| 1445 var rightType = rules.getStaticType(right); | 1445 var rightType = rules.getStaticType(right); |
| 1446 | 1446 |
| 1447 var code; | 1447 var code; |
| 1448 if (op.type.isEqualityOperator) { | 1448 if (op.type.isEqualityOperator) { |
| 1449 // If we statically know LHS or RHS is null we can generate a clean check. | 1449 // If we statically know LHS or RHS is null we can generate a clean check. |
| 1450 // We can also do this if the left hand side is a primitive type, because | 1450 // We can also do this if both sides are the same primitive type. |
| 1451 // we know then it doesn't have an overridden. | 1451 if (_canUsePrimitiveEquality(left, right)) { |
| 1452 if (_isNull(left) || _isNull(right) || typeIsPrimitiveInJS(leftType)) { | 1452 code = op.type == TokenType.EQ_EQ ? '# == #' : '# != #'; |
| 1453 // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-strict-equa
lity-comparison | |
| 1454 code = op.type == TokenType.EQ_EQ ? '# === #' : '# !== #'; | |
| 1455 } else { | 1453 } else { |
| 1456 var bang = op.type == TokenType.BANG_EQ ? '!' : ''; | 1454 var bang = op.type == TokenType.BANG_EQ ? '!' : ''; |
| 1457 code = '${bang}dart.equals(#, #)'; | 1455 code = '${bang}dart.equals(#, #)'; |
| 1458 } | 1456 } |
| 1459 return js.call(code, [_visit(left), _visit(right)]); | 1457 return js.call(code, [_visit(left), _visit(right)]); |
| 1460 } else if (binaryOperationIsPrimitive(leftType, rightType)) { | 1458 } else if (binaryOperationIsPrimitive(leftType, rightType)) { |
| 1461 // special cases where we inline the operation | 1459 // special cases where we inline the operation |
| 1462 // these values are assumed to be non-null (determined by the checker) | 1460 // these values are assumed to be non-null (determined by the checker) |
| 1463 // TODO(jmesserly): it would be nice to just inline the method from core, | 1461 // TODO(jmesserly): it would be nice to just inline the method from core, |
| 1464 // instead of special cases here. | 1462 // instead of special cases here. |
| (...skipping 28 matching lines...) Expand all Loading... |
| 1493 _visit(left), | 1491 _visit(left), |
| 1494 _visit(right) | 1492 _visit(right) |
| 1495 ]); | 1493 ]); |
| 1496 } else { | 1494 } else { |
| 1497 // Generic static-dispatch, user-defined operator code path. | 1495 // Generic static-dispatch, user-defined operator code path. |
| 1498 return js.call('#.#(#)', [_visit(left), opString, _visit(right)]); | 1496 return js.call('#.#(#)', [_visit(left), opString, _visit(right)]); |
| 1499 } | 1497 } |
| 1500 } | 1498 } |
| 1501 } | 1499 } |
| 1502 | 1500 |
| 1501 /// If the type [t] is [int] or [double], returns [num]. |
| 1502 /// Otherwise returns [t]. |
| 1503 DartType _canonicalizeNumTypes(DartType t) { |
| 1504 var numType = rules.provider.numType; |
| 1505 if (t is InterfaceType && t.superclass == numType) return numType; |
| 1506 return t; |
| 1507 } |
| 1508 |
| 1509 bool _canUsePrimitiveEquality(Expression left, Expression right) { |
| 1510 if (_isNull(left) || _isNull(right)) return true; |
| 1511 |
| 1512 var leftType = _canonicalizeNumTypes(rules.getStaticType(left)); |
| 1513 var rightType = _canonicalizeNumTypes(rules.getStaticType(right)); |
| 1514 return _isJSBuiltinType(leftType) && leftType == rightType; |
| 1515 } |
| 1516 |
| 1503 bool _isNull(Expression expr) => expr is NullLiteral; | 1517 bool _isNull(Expression expr) => expr is NullLiteral; |
| 1504 | 1518 |
| 1505 // TODO(jmesserly, vsm): Refactor this logic. | 1519 // TODO(jmesserly, vsm): Refactor this logic. |
| 1506 SimpleIdentifier _createTemporary(String name, DartType type) { | 1520 SimpleIdentifier _createTemporary(String name, DartType type) { |
| 1507 // We use an invalid source location to signal that this is a temporary. | 1521 // We use an invalid source location to signal that this is a temporary. |
| 1508 // See [_isTemporary]. | 1522 // See [_isTemporary]. |
| 1509 // TODO(jmesserly): alternatives are | 1523 // TODO(jmesserly): alternatives are |
| 1510 // * (ab)use Element.isSynthetic, which isn't currently used for | 1524 // * (ab)use Element.isSynthetic, which isn't currently used for |
| 1511 // LocalVariableElementImpl, so we could repurpose to mean "temp". | 1525 // LocalVariableElementImpl, so we could repurpose to mean "temp". |
| 1512 // * add a new property to LocalVariableElementImpl. | 1526 // * add a new property to LocalVariableElementImpl. |
| (...skipping 840 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2353 | 2367 |
| 2354 // TODO(jmesserly): in many cases marking the end will be unncessary. | 2368 // TODO(jmesserly): in many cases marking the end will be unncessary. |
| 2355 printer.mark(_location(node.end)); | 2369 printer.mark(_location(node.end)); |
| 2356 } | 2370 } |
| 2357 | 2371 |
| 2358 String _getIdentifier(AstNode node) { | 2372 String _getIdentifier(AstNode node) { |
| 2359 if (node is SimpleIdentifier) return node.name; | 2373 if (node is SimpleIdentifier) return node.name; |
| 2360 return null; | 2374 return null; |
| 2361 } | 2375 } |
| 2362 } | 2376 } |
| OLD | NEW |