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 visitInstanceCreationExpression(InstanceCreationExpression node) { | 1440 visitInstanceCreationExpression(InstanceCreationExpression node) { |
1441 return js.call( | 1441 return js.call( |
1442 'new #(#)', [_visit(node.constructorName), _visit(node.argumentList)]); | 1442 'new #(#)', [_visit(node.constructorName), _visit(node.argumentList)]); |
1443 } | 1443 } |
1444 | 1444 |
1445 /// True if this type is built-in to JS, and we use the values unwrapped. | 1445 /// True if this type is built-in to JS, and we use the values unwrapped. |
1446 /// For these types we generate a calling convention via static | 1446 /// For these types we generate a calling convention via static |
1447 /// "extension methods". This allows types to be extended without adding | 1447 /// "extension methods". This allows types to be extended without adding |
1448 /// extensions directly on the prototype. | 1448 /// extensions directly on the prototype. |
1449 bool _isJSBuiltinType(DartType t) => | 1449 bool _isJSBuiltinType(DartType t) => |
1450 rules.isNumType(t) || rules.isStringType(t) || rules.isBoolType(t); | 1450 typeIsPrimitiveInJS(t) || rules.isStringType(t); |
1451 | 1451 |
1452 bool typeIsPrimitiveInJS(DartType t) => !rules.isDynamic(t) && | 1452 bool typeIsPrimitiveInJS(DartType t) => (rules.isIntType(t) || |
Jacob
2015/04/13 23:23:16
was !rules.isDynamic(t) never needed?
Jennifer Messerly
2015/04/14 17:44:02
yeah, it didn't make sense to me (how can int/doub
| |
1453 (rules.isIntType(t) || | 1453 rules.isDoubleType(t) || |
1454 rules.isDoubleType(t) || | 1454 rules.isBoolType(t) || |
1455 rules.isBoolType(t) || | 1455 rules.isNumType(t)); |
1456 rules.isNumType(t)); | |
1457 | 1456 |
1458 bool typeIsNonNullablePrimitiveInJS(DartType t) => | 1457 bool typeIsNonNullablePrimitiveInJS(DartType t) => |
1459 typeIsPrimitiveInJS(t) && rules.isNonNullableType(t); | 1458 typeIsPrimitiveInJS(t) && rules.isNonNullableType(t); |
1460 | 1459 |
1461 bool binaryOperationIsPrimitive(DartType leftT, DartType rightT) => | 1460 bool binaryOperationIsPrimitive(DartType leftT, DartType rightT) => |
1462 typeIsPrimitiveInJS(leftT) && typeIsPrimitiveInJS(rightT); | 1461 typeIsPrimitiveInJS(leftT) && typeIsPrimitiveInJS(rightT); |
1463 | 1462 |
1464 bool unaryOperationIsPrimitive(DartType t) => typeIsPrimitiveInJS(t); | 1463 bool unaryOperationIsPrimitive(DartType t) => typeIsPrimitiveInJS(t); |
1465 | 1464 |
1466 bool _isNonNullableExpression(Expression expr) { | 1465 bool _isNonNullableExpression(Expression expr) { |
(...skipping 12 matching lines...) Expand all Loading... | |
1479 return _isNonNullableExpression(expr.expression); | 1478 return _isNonNullableExpression(expr.expression); |
1480 } | 1479 } |
1481 DartType type = null; | 1480 DartType type = null; |
1482 if (expr is BinaryExpression) { | 1481 if (expr is BinaryExpression) { |
1483 type = getStaticType(expr.leftOperand); | 1482 type = getStaticType(expr.leftOperand); |
1484 } else if (expr is PrefixExpression) { | 1483 } else if (expr is PrefixExpression) { |
1485 type = getStaticType(expr.operand); | 1484 type = getStaticType(expr.operand); |
1486 } else if (expr is PostfixExpression) { | 1485 } else if (expr is PostfixExpression) { |
1487 type = getStaticType(expr.operand); | 1486 type = getStaticType(expr.operand); |
1488 } | 1487 } |
1489 if (type != null && typeIsPrimitiveInJS(type)) { | 1488 if (type != null && _isJSBuiltinType(type)) { |
1490 return true; | 1489 return true; |
1491 } | 1490 } |
1492 if (expr is MethodInvocation) { | 1491 if (expr is MethodInvocation) { |
1493 // TODO(vsm): This logic overlaps with the resolver. | 1492 // TODO(vsm): This logic overlaps with the resolver. |
1494 // Where is the best place to put this? | 1493 // Where is the best place to put this? |
1495 var e = expr.methodName.staticElement; | 1494 var e = expr.methodName.staticElement; |
1496 if (e is FunctionElement && | 1495 if (e is FunctionElement && |
1497 e.library.name == '_foreign_helper' && | 1496 e.library.name == '_foreign_helper' && |
1498 e.name == 'JS') { | 1497 e.name == 'JS') { |
1499 // Fix types for JS builtin calls. | 1498 // Fix types for JS builtin calls. |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1537 // We can also do this if both sides are the same primitive type. | 1536 // We can also do this if both sides are the same primitive type. |
1538 if (_canUsePrimitiveEquality(left, right)) { | 1537 if (_canUsePrimitiveEquality(left, right)) { |
1539 code = op.type == TokenType.EQ_EQ ? '# == #' : '# != #'; | 1538 code = op.type == TokenType.EQ_EQ ? '# == #' : '# != #'; |
1540 } else { | 1539 } else { |
1541 var bang = op.type == TokenType.BANG_EQ ? '!' : ''; | 1540 var bang = op.type == TokenType.BANG_EQ ? '!' : ''; |
1542 code = '${bang}dart.equals(#, #)'; | 1541 code = '${bang}dart.equals(#, #)'; |
1543 } | 1542 } |
1544 return js.call(code, [_visit(left), _visit(right)]); | 1543 return js.call(code, [_visit(left), _visit(right)]); |
1545 } | 1544 } |
1546 | 1545 |
1547 if (binaryOperationIsPrimitive(leftType, rightType)) { | 1546 if (binaryOperationIsPrimitive(leftType, rightType) || |
1547 rules.isStringType(leftType) && op.type == TokenType.PLUS) { | |
1548 | |
1548 // special cases where we inline the operation | 1549 // special cases where we inline the operation |
1549 // these values are assumed to be non-null (determined by the checker) | 1550 // these values are assumed to be non-null (determined by the checker) |
1550 // TODO(jmesserly): it would be nice to just inline the method from core, | 1551 // TODO(jmesserly): it would be nice to just inline the method from core, |
1551 // instead of special cases here. | 1552 // instead of special cases here. |
1552 if (op.type == TokenType.TILDE_SLASH) { | 1553 if (op.type == TokenType.TILDE_SLASH) { |
1553 // `a ~/ b` is equivalent to `(a / b).truncate()` | 1554 // `a ~/ b` is equivalent to `(a / b).truncate()` |
1554 code = '(# / #).truncate()'; | 1555 code = '(# / #).truncate()'; |
1555 } else { | 1556 } else { |
1556 // TODO(vsm): When do Dart ops not map to JS? | 1557 // TODO(vsm): When do Dart ops not map to JS? |
1557 code = '# $op #'; | 1558 code = '# $op #'; |
(...skipping 996 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2554 if (args.isNotEmpty && args[0] is NamedExpression) { | 2555 if (args.isNotEmpty && args[0] is NamedExpression) { |
2555 NamedExpression named = args[0]; | 2556 NamedExpression named = args[0]; |
2556 if (named.name.label.name == argName && | 2557 if (named.name.label.name == argName && |
2557 named.expression is StringLiteral) { | 2558 named.expression is StringLiteral) { |
2558 return (named.expression as StringLiteral).stringValue; | 2559 return (named.expression as StringLiteral).stringValue; |
2559 } | 2560 } |
2560 } | 2561 } |
2561 } | 2562 } |
2562 return null; | 2563 return null; |
2563 } | 2564 } |
OLD | NEW |