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 |