| 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, 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 1780 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1791 if (expr is Conversion) { | 1791 if (expr is Conversion) { |
| 1792 return _isNonNullableExpression(expr.expression); | 1792 return _isNonNullableExpression(expr.expression); |
| 1793 } | 1793 } |
| 1794 if (expr is SimpleIdentifier) { | 1794 if (expr is SimpleIdentifier) { |
| 1795 // Type literals are not null. | 1795 // Type literals are not null. |
| 1796 Element e = expr.staticElement; | 1796 Element e = expr.staticElement; |
| 1797 if (e is ClassElement || e is FunctionTypeAliasElement) return true; | 1797 if (e is ClassElement || e is FunctionTypeAliasElement) return true; |
| 1798 } | 1798 } |
| 1799 DartType type = null; | 1799 DartType type = null; |
| 1800 if (expr is BinaryExpression) { | 1800 if (expr is BinaryExpression) { |
| 1801 switch (expr.operator.type) { |
| 1802 case TokenType.EQ_EQ: |
| 1803 case TokenType.BANG_EQ: |
| 1804 case TokenType.AMPERSAND_AMPERSAND: |
| 1805 case TokenType.BAR_BAR: |
| 1806 return true; |
| 1807 } |
| 1801 type = getStaticType(expr.leftOperand); | 1808 type = getStaticType(expr.leftOperand); |
| 1802 } else if (expr is PrefixExpression) { | 1809 } else if (expr is PrefixExpression) { |
| 1810 if (expr.operator.type == TokenType.BANG) return true; |
| 1803 type = getStaticType(expr.operand); | 1811 type = getStaticType(expr.operand); |
| 1804 } else if (expr is PostfixExpression) { | 1812 } else if (expr is PostfixExpression) { |
| 1805 type = getStaticType(expr.operand); | 1813 type = getStaticType(expr.operand); |
| 1806 } | 1814 } |
| 1807 if (type != null && _isJSBuiltinType(type)) { | 1815 if (type != null && _isJSBuiltinType(type)) { |
| 1808 return true; | 1816 return true; |
| 1809 } | 1817 } |
| 1810 if (expr is MethodInvocation) { | 1818 if (expr is MethodInvocation) { |
| 1811 // TODO(vsm): This logic overlaps with the resolver. | 1819 // TODO(vsm): This logic overlaps with the resolver. |
| 1812 // Where is the best place to put this? | 1820 // Where is the best place to put this? |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1828 if (!types.split('|').contains('Null')) { | 1836 if (!types.split('|').contains('Null')) { |
| 1829 return true; | 1837 return true; |
| 1830 } | 1838 } |
| 1831 } | 1839 } |
| 1832 } | 1840 } |
| 1833 } | 1841 } |
| 1834 return false; | 1842 return false; |
| 1835 } | 1843 } |
| 1836 | 1844 |
| 1837 JS.Expression notNull(Expression expr) { | 1845 JS.Expression notNull(Expression expr) { |
| 1838 if (_isNonNullableExpression(expr)) { | 1846 if (expr == null) return null; |
| 1839 return _visit(expr); | 1847 var jsExpr = _visit(expr); |
| 1840 } else { | 1848 if (_isNonNullableExpression(expr)) return jsExpr; |
| 1841 return js.call('dart.notNull(#)', _visit(expr)); | 1849 return js.call('dart.notNull(#)', jsExpr); |
| 1842 } | |
| 1843 } | 1850 } |
| 1844 | 1851 |
| 1845 @override | 1852 @override |
| 1846 JS.Expression visitBinaryExpression(BinaryExpression node) { | 1853 JS.Expression visitBinaryExpression(BinaryExpression node) { |
| 1847 var op = node.operator; | 1854 var op = node.operator; |
| 1848 var left = node.leftOperand; | 1855 var left = node.leftOperand; |
| 1849 var right = node.rightOperand; | 1856 var right = node.rightOperand; |
| 1850 var leftType = getStaticType(left); | 1857 var leftType = getStaticType(left); |
| 1851 var rightType = getStaticType(right); | 1858 var rightType = getStaticType(right); |
| 1852 | 1859 |
| (...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2195 /// Those two nodes are special because they're both allowed on left side of | 2202 /// Those two nodes are special because they're both allowed on left side of |
| 2196 /// an assignment expression and cascades. | 2203 /// an assignment expression and cascades. |
| 2197 Expression _getTarget(node) { | 2204 Expression _getTarget(node) { |
| 2198 assert(node is IndexExpression || node is PropertyAccess); | 2205 assert(node is IndexExpression || node is PropertyAccess); |
| 2199 return node.isCascaded ? _cascadeTarget : node.target; | 2206 return node.isCascaded ? _cascadeTarget : node.target; |
| 2200 } | 2207 } |
| 2201 | 2208 |
| 2202 @override | 2209 @override |
| 2203 visitConditionalExpression(ConditionalExpression node) { | 2210 visitConditionalExpression(ConditionalExpression node) { |
| 2204 return js.call('# ? # : #', [ | 2211 return js.call('# ? # : #', [ |
| 2205 _visit(node.condition), | 2212 notNull(node.condition), |
| 2206 _visit(node.thenExpression), | 2213 _visit(node.thenExpression), |
| 2207 _visit(node.elseExpression) | 2214 _visit(node.elseExpression) |
| 2208 ]); | 2215 ]); |
| 2209 } | 2216 } |
| 2210 | 2217 |
| 2211 @override | 2218 @override |
| 2212 visitThrowExpression(ThrowExpression node) { | 2219 visitThrowExpression(ThrowExpression node) { |
| 2213 var expr = _visit(node.expression); | 2220 var expr = _visit(node.expression); |
| 2214 if (node.parent is ExpressionStatement) { | 2221 if (node.parent is ExpressionStatement) { |
| 2215 return js.statement('throw #;', expr); | 2222 return js.statement('throw #;', expr); |
| 2216 } else { | 2223 } else { |
| 2217 return js.call('dart.throw_(#)', expr); | 2224 return js.call('dart.throw_(#)', expr); |
| 2218 } | 2225 } |
| 2219 } | 2226 } |
| 2220 | 2227 |
| 2221 @override | 2228 @override |
| 2222 visitRethrowExpression(RethrowExpression node) { | 2229 visitRethrowExpression(RethrowExpression node) { |
| 2223 if (node.parent is ExpressionStatement) { | 2230 if (node.parent is ExpressionStatement) { |
| 2224 return js.statement('throw #;', _visit(_catchParameter)); | 2231 return js.statement('throw #;', _visit(_catchParameter)); |
| 2225 } else { | 2232 } else { |
| 2226 return js.call('dart.throw_(#)', _visit(_catchParameter)); | 2233 return js.call('dart.throw_(#)', _visit(_catchParameter)); |
| 2227 } | 2234 } |
| 2228 } | 2235 } |
| 2229 | 2236 |
| 2230 @override | 2237 @override |
| 2231 JS.If visitIfStatement(IfStatement node) { | 2238 JS.If visitIfStatement(IfStatement node) { |
| 2232 return new JS.If(_visit(node.condition), _visit(node.thenStatement), | 2239 return new JS.If(notNull(node.condition), _visit(node.thenStatement), |
| 2233 _visit(node.elseStatement)); | 2240 _visit(node.elseStatement)); |
| 2234 } | 2241 } |
| 2235 | 2242 |
| 2236 @override | 2243 @override |
| 2237 JS.For visitForStatement(ForStatement node) { | 2244 JS.For visitForStatement(ForStatement node) { |
| 2238 var init = _visit(node.initialization); | 2245 var init = _visit(node.initialization); |
| 2239 if (init == null) init = _visit(node.variables); | 2246 if (init == null) init = _visit(node.variables); |
| 2240 var update = _visitListToBinary(node.updaters, ','); | 2247 var update = _visitListToBinary(node.updaters, ','); |
| 2241 if (update != null) update = update.toVoidExpression(); | 2248 if (update != null) update = update.toVoidExpression(); |
| 2242 return new JS.For(init, _visit(node.condition), update, _visit(node.body)); | 2249 return new JS.For(init, notNull(node.condition), update, _visit(node.body)); |
| 2243 } | 2250 } |
| 2244 | 2251 |
| 2245 @override | 2252 @override |
| 2246 JS.While visitWhileStatement(WhileStatement node) { | 2253 JS.While visitWhileStatement(WhileStatement node) { |
| 2247 return new JS.While(_visit(node.condition), _visit(node.body)); | 2254 return new JS.While(notNull(node.condition), _visit(node.body)); |
| 2248 } | 2255 } |
| 2249 | 2256 |
| 2250 @override | 2257 @override |
| 2251 JS.Do visitDoStatement(DoStatement node) { | 2258 JS.Do visitDoStatement(DoStatement node) { |
| 2252 return new JS.Do(_visit(node.body), _visit(node.condition)); | 2259 return new JS.Do(_visit(node.body), notNull(node.condition)); |
| 2253 } | 2260 } |
| 2254 | 2261 |
| 2255 @override | 2262 @override |
| 2256 JS.ForOf visitForEachStatement(ForEachStatement node) { | 2263 JS.ForOf visitForEachStatement(ForEachStatement node) { |
| 2257 var init = _visit(node.identifier); | 2264 var init = _visit(node.identifier); |
| 2258 if (init == null) { | 2265 if (init == null) { |
| 2259 init = js.call('let #', node.loopVariable.identifier.name); | 2266 init = js.call('let #', node.loopVariable.identifier.name); |
| 2260 } | 2267 } |
| 2261 return new JS.ForOf(init, _visit(node.iterable), _visit(node.body)); | 2268 return new JS.ForOf(init, _visit(node.iterable), _visit(node.body)); |
| 2262 } | 2269 } |
| (...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2551 /// Point(x, y) { | 2558 /// Point(x, y) { |
| 2552 /// this[_x] = x; | 2559 /// this[_x] = x; |
| 2553 /// this[_y] = y; | 2560 /// this[_y] = y; |
| 2554 /// } | 2561 /// } |
| 2555 /// get x() { return this[_x]; } | 2562 /// get x() { return this[_x]; } |
| 2556 /// get y() { return this[_y]; } | 2563 /// get y() { return this[_y]; } |
| 2557 /// } | 2564 /// } |
| 2558 /// | 2565 /// |
| 2559 /// For user-defined operators the following names are allowed: | 2566 /// For user-defined operators the following names are allowed: |
| 2560 /// | 2567 /// |
| 2561 /// <, >, <=, >=, ==, -, +, /, ˜/, *, %, |, ˆ, &, <<, >>, []=, [], ˜ | 2568 /// <, >, <=, >=, ==, -, +, /, ~/, *, %, |, ^, &, <<, >>, []=, [], ~ |
| 2562 /// | 2569 /// |
| 2563 /// They generate code like: | 2570 /// They generate code like: |
| 2564 /// | 2571 /// |
| 2565 /// x['+'](y) | 2572 /// x['+'](y) |
| 2566 /// | 2573 /// |
| 2567 /// There are three exceptions: [], []= and unary -. | 2574 /// There are three exceptions: [], []= and unary -. |
| 2568 /// The indexing operators we use `get` and `set` instead: | 2575 /// The indexing operators we use `get` and `set` instead: |
| 2569 /// | 2576 /// |
| 2570 /// x.get('hi') | 2577 /// x.get('hi') |
| 2571 /// x.set('hi', 123) | 2578 /// x.set('hi', 123) |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2699 | 2706 |
| 2700 /// A special kind of element created by the compiler, signifying a temporary | 2707 /// A special kind of element created by the compiler, signifying a temporary |
| 2701 /// variable. These objects use instance equality, and should be shared | 2708 /// variable. These objects use instance equality, and should be shared |
| 2702 /// everywhere in the tree where they are treated as the same variable. | 2709 /// everywhere in the tree where they are treated as the same variable. |
| 2703 class TemporaryVariableElement extends LocalVariableElementImpl { | 2710 class TemporaryVariableElement extends LocalVariableElementImpl { |
| 2704 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); | 2711 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); |
| 2705 | 2712 |
| 2706 int get hashCode => identityHashCode(this); | 2713 int get hashCode => identityHashCode(this); |
| 2707 bool operator ==(Object other) => identical(this, other); | 2714 bool operator ==(Object other) => identical(this, other); |
| 2708 } | 2715 } |
| OLD | NEW |